diff --git a/sbin/atacontrol/atacontrol.c b/sbin/atacontrol/atacontrol.c index 49e4fa231ae3..29599eb3dc41 100644 --- a/sbin/atacontrol/atacontrol.c +++ b/sbin/atacontrol/atacontrol.c @@ -42,7 +42,7 @@ static const char * mode2str(int mode) { - switch (mode) { + switch (mode & 0xff) { case ATA_PIO: return "BIOSPIO"; case ATA_PIO0: return "PIO0"; case ATA_PIO1: return "PIO1"; @@ -59,13 +59,23 @@ mode2str(int mode) case ATA_UDMA4: return "UDMA66"; case ATA_UDMA5: return "UDMA100"; case ATA_UDMA6: return "UDMA133"; - case ATA_SA150: return "SATA150"; - case ATA_SA300: return "SATA300"; case ATA_DMA: return "BIOSDMA"; default: return "???"; } } +static const char * +satarev2str(int mode) +{ + switch ((mode & 0xff00) >> 8) { + case 0: return ""; + case 1: return "SATA 1.5Gb/s"; + case 2: return "SATA 3Gb/s"; + case 3: return "SATA 6Gb/s"; + default: return "???"; + } +} + static int str2mode(char *str) { @@ -79,7 +89,9 @@ str2mode(char *str) if (!strcasecmp(str, "WDMA1")) return ATA_WDMA1; if (!strcasecmp(str, "WDMA2")) return ATA_WDMA2; if (!strcasecmp(str, "UDMA0")) return ATA_UDMA0; + if (!strcasecmp(str, "UDMA16")) return ATA_UDMA0; if (!strcasecmp(str, "UDMA1")) return ATA_UDMA1; + if (!strcasecmp(str, "UDMA25")) return ATA_UDMA1; if (!strcasecmp(str, "UDMA2")) return ATA_UDMA2; if (!strcasecmp(str, "UDMA33")) return ATA_UDMA2; if (!strcasecmp(str, "UDMA3")) return ATA_UDMA3; @@ -90,8 +102,6 @@ str2mode(char *str) if (!strcasecmp(str, "UDMA100")) return ATA_UDMA5; if (!strcasecmp(str, "UDMA6")) return ATA_UDMA6; if (!strcasecmp(str, "UDMA133")) return ATA_UDMA6; - if (!strcasecmp(str, "SATA150")) return ATA_SA150; - if (!strcasecmp(str, "SATA300")) return ATA_SA300; if (!strcasecmp(str, "BIOSDMA")) return ATA_DMA; return -1; } @@ -382,7 +392,8 @@ main(int argc, char **argv) if (argc == 3 || argc == 4) { if (ioctl(fd, IOCATAGMODE, &mode) < 0) err(1, "ioctl(IOCATAGMODE)"); - printf("current mode = %s\n", mode2str(mode)); + printf("current mode = %s %s\n", + mode2str(mode), satarev2str(mode)); } exit(EX_OK); } diff --git a/sys/arm/mv/mv_sata.c b/sys/arm/mv/mv_sata.c index 35939563c50c..01713daa27cb 100644 --- a/sys/arm/mv/mv_sata.c +++ b/sys/arm/mv/mv_sata.c @@ -136,7 +136,8 @@ static int sata_channel_detach(device_t dev); static int sata_channel_begin_transaction(struct ata_request *request); static int sata_channel_end_transaction(struct ata_request *request); static int sata_channel_status(device_t dev); -static void sata_channel_setmode(device_t parent, device_t dev); +static int sata_channel_setmode(device_t dev, int target, int mode); +static int sata_channel_getrev(device_t dev, int target); static void sata_channel_reset(device_t dev); static void sata_channel_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); @@ -423,7 +424,7 @@ sata_channel_attach(device_t dev) ch->dev = dev; ch->unit = device_get_unit(dev); - ch->flags |= ATA_USE_16BIT | ATA_NO_SLAVE; + ch->flags |= ATA_USE_16BIT | ATA_NO_SLAVE | ATA_SATA; /* Set legacy ATA resources. */ for (i = ATA_DATA; i <= ATA_COMMAND; i++) { @@ -748,19 +749,22 @@ sata_channel_reset(device_t dev) SATA_OUTL(sc, SATA_EDMA_IEMR(ch->unit), 0xFFFFFFFF); } -static void -sata_channel_setmode(device_t parent, device_t dev) +static int +sata_channel_setmode(device_t parent, int target, int mode) { - struct ata_device *atadev; - - atadev = device_get_softc(dev); /* Disable EDMA before using legacy registers */ sata_edma_ctrl(parent, 0); + return (ata_sata_setmode(parent, target, mode)); +} - ata_sata_setmode(dev, ATA_PIO_MAX); - if (atadev->mode >= ATA_DMA) - ata_sata_setmode(dev, atadev->mode); +static int +sata_channel_getrev(device_t parent, int target) +{ + + /* Disable EDMA before using legacy registers */ + sata_edma_ctrl(parent, 0); + return (ata_sata_getrev(parent, target)); } static void @@ -849,6 +853,7 @@ static device_method_t sata_channel_methods[] = { /* ATA channel interface */ DEVMETHOD(ata_reset, sata_channel_reset), DEVMETHOD(ata_setmode, sata_channel_setmode), + DEVMETHOD(ata_getrev, sata_channel_getrev), { 0, 0 } }; diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c index 89f51538602d..a162623547b5 100644 --- a/sys/cam/ata/ata_xpt.c +++ b/sys/cam/ata/ata_xpt.c @@ -366,7 +366,7 @@ negotiate: cts.xport_specific.sata.valid = CTS_SATA_VALID_MODE; } xpt_action((union ccb *)&cts); - /* Fetch user modes from SIM. */ + /* Fetch current modes from SIM. */ bzero(&cts, sizeof(cts)); xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; @@ -395,10 +395,25 @@ negotiate: } case PROBE_SET_MULTI: { - u_int sectors; - - sectors = max(1, min(ident_buf->sectors_intr & 0xff, 16)); + u_int sectors, bytecount; + bytecount = 8192; /* SATA maximum */ + /* Fetch user bytecount from SIM. */ + bzero(&cts, sizeof(cts)); + xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); + cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; + cts.type = CTS_TYPE_USER_SETTINGS; + xpt_action((union ccb *)&cts); + if (path->device->transport == XPORT_ATA) { + if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) + bytecount = cts.xport_specific.ata.bytecount; + } else { + if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) + bytecount = cts.xport_specific.sata.bytecount; + } + /* Honor device capabilities. */ + sectors = max(1, min(ident_buf->sectors_intr & 0xff, + bytecount / ata_logical_sector_size(ident_buf))); /* Report bytecount to SIM. */ bzero(&cts, sizeof(cts)); xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); @@ -414,6 +429,20 @@ negotiate: cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; } xpt_action((union ccb *)&cts); + /* Fetch current bytecount from SIM. */ + bzero(&cts, sizeof(cts)); + 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); + if (path->device->transport == XPORT_ATA) { + if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) + bytecount = cts.xport_specific.ata.bytecount; + } else { + if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) + bytecount = cts.xport_specific.sata.bytecount; + } + sectors = bytecount / ata_logical_sector_size(ident_buf); cam_fill_ataio(ataio, 1, @@ -427,6 +456,45 @@ negotiate: break; } case PROBE_INQUIRY: + { + u_int bytecount; + + bytecount = 8192; /* SATA maximum */ + /* Fetch user bytecount from SIM. */ + bzero(&cts, sizeof(cts)); + xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); + cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; + cts.type = CTS_TYPE_USER_SETTINGS; + xpt_action((union ccb *)&cts); + if (path->device->transport == XPORT_ATA) { + if (cts.xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) + bytecount = cts.xport_specific.ata.bytecount; + } else { + if (cts.xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) + bytecount = cts.xport_specific.sata.bytecount; + } + /* Honor device capabilities. */ + bytecount &= ~1; + bytecount = max(2, min(65534, bytecount)); + if (ident_buf->satacapabilities != 0x0000 && + ident_buf->satacapabilities != 0xffff) { + bytecount = min(8192, bytecount); + } + /* Report bytecount to SIM. */ + bzero(&cts, sizeof(cts)); + 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; + if (path->device->transport == XPORT_ATA) { + cts.xport_specific.ata.bytecount = bytecount; + cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT; + } else { + cts.xport_specific.sata.bytecount = bytecount; + cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT; + } + xpt_action((union ccb *)&cts); + /* FALLTHROUGH */ + } case PROBE_FULL_INQUIRY: { u_int inquiry_len; diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c index 7bd6158f8693..a6dabc2e96c5 100644 --- a/sys/cam/scsi/scsi_cd.c +++ b/sys/cam/scsi/scsi_cd.c @@ -673,6 +673,7 @@ cdregister(struct cam_periph *periph, void *arg) softc->quirks = CD_Q_NONE; /* Check if the SIM does not want 6 byte 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); @@ -726,6 +727,12 @@ cdregister(struct cam_periph *periph, void *arg) softc->disk->d_name = "cd"; softc->disk->d_unit = periph->unit_number; softc->disk->d_drv1 = periph; + if (cpi.maxio == 0) + softc->disk->d_maxsize = DFLTPHYS; /* traditional default */ + else if (cpi.maxio > MAXPHYS) + softc->disk->d_maxsize = MAXPHYS; /* for safety */ + else + softc->disk->d_maxsize = cpi.maxio; softc->disk->d_flags = 0; disk_create(softc->disk, DISK_VERSION); cam_periph_lock(periph); @@ -2768,7 +2775,6 @@ cdcheckmedia(struct cam_periph *periph) softc = (struct cd_softc *)periph->softc; cdprevent(periph, PR_PREVENT); - softc->disk->d_maxsize = DFLTPHYS; softc->disk->d_sectorsize = 2048; softc->disk->d_mediasize = 0; @@ -2870,7 +2876,6 @@ cdcheckmedia(struct cam_periph *periph) } softc->flags |= CD_FLAG_VALID_TOC; - softc->disk->d_maxsize = DFLTPHYS; softc->disk->d_sectorsize = softc->params.blksize; softc->disk->d_mediasize = (off_t)softc->params.blksize * softc->params.disksize; diff --git a/sys/conf/NOTES b/sys/conf/NOTES index b74ac72722ab..57f2dfd61868 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1718,9 +1718,15 @@ hint.ata.1.irq="15" # else the device numbers are dynamically allocated. # ATA_REQUEST_TIMEOUT: the number of seconds to wait for an ATA request # before timing out. +# ATA_CAM: Turn ata(4) subsystem controller drivers into cam(4) +# interface modules. This deprecates all ata(4) +# peripheral device drivers (atadisk, ataraid, atapicd, +# atapifd. atapist, atapicam) and all user-level APIs. +# cam(4) drivers and APIs will be connected instead. options ATA_STATIC_ID #options ATA_REQUEST_TIMEOUT=10 +#options ATA_CAM # # Standard floppy disk controllers and floppy tapes, supports diff --git a/sys/conf/options b/sys/conf/options index f73ed162b2f9..5405559567e7 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -351,6 +351,7 @@ ISCSI_INITIATOR_DEBUG opt_iscsi_initiator.h ATA_STATIC_ID opt_ata.h ATA_NOPCI opt_ata.h ATA_REQUEST_TIMEOUT opt_ata.h +ATA_CAM opt_ata.h # Net stuff. ACCEPT_FILTER_DATA diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index a1a6f27556a2..2fc59879840f 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -50,6 +50,16 @@ __FBSDID("$FreeBSD$"); #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,10 @@ ata_attach(device_t dev) { struct ata_channel *ch = device_get_softc(dev); int error, rid; +#ifdef ATA_CAM + struct cam_devq *devq; + int i; +#endif /* check that we have a virgin channel to attach */ if (ch->r_irq) @@ -129,11 +150,23 @@ ata_attach(device_t dev) mtx_init(&ch->queue_mtx, "ATA queue lock", NULL, MTX_DEF); TAILQ_INIT(&ch->ata_queue); TASK_INIT(&ch->conntask, 0, ata_conn_event, dev); +#ifdef ATA_CAM + for (i = 0; i < 16; i++) { + ch->user[i].mode = 0; + if (ch->flags & ATA_SATA) + ch->user[i].bytecount = 8192; + else + ch->user[i].bytecount = MAXPHYS; + ch->curr[i] = ch->user[i]; + } +#endif /* 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 +187,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 +252,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 +260,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 +290,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 +302,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 +389,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 +417,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 +430,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 +446,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 +501,71 @@ 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 +} + +void +ata_print_cable(device_t dev, u_int8_t *who) +{ + device_printf(dev, + "DMA limited to UDMA33, %s found non-ATA66 cable\n", who); +} + +int +ata_check_80pin(device_t dev, int mode) +{ + struct ata_device *atadev = device_get_softc(dev); + + if (!ata_dma_check_80pin) { + if (bootverbose) + device_printf(dev, "Skipping 80pin cable check\n"); + return mode; + } + + if (mode > ATA_UDMA2 && !(atadev->param.hwres & ATA_CABLE_ID)) { + ata_print_cable(dev, "device"); + mode = ATA_UDMA2; + } + return mode; +} + +void +ata_setmode(device_t dev) +{ + struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + struct ata_device *atadev = device_get_softc(dev); + int error, mode, pmode; + + mode = atadev->mode; + do { + pmode = mode = ata_limit_mode(dev, mode, ATA_DMA_MAX); + mode = ATA_SETMODE(device_get_parent(dev), atadev->unit, mode); + if ((ch->flags & (ATA_CHECKS_CABLE | ATA_SATA)) == 0) + mode = ata_check_80pin(dev, mode); + } while (pmode != mode); /* Interate till successfull negotiation. */ + error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); + if (bootverbose) + device_printf(dev, "%ssetting %s\n", + (error) ? "FAILURE " : "", ata_mode2str(mode)); + atadev->mode = mode; } /* * 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 +647,7 @@ ata_ioctl(struct cdev *dev, u_long cmd, caddr_t data, } return error; } +#endif int ata_device_ioctl(device_t dev, u_long cmd, caddr_t data) @@ -549,11 +730,12 @@ ata_device_ioctl(device_t dev, u_long cmd, caddr_t data) case IOCATASMODE: atadev->mode = *mode; - ATA_SETMODE(device_get_parent(dev), dev); + ata_setmode(dev); return 0; case IOCATAGMODE: - *mode = atadev->mode; + *mode = atadev->mode | + (ATA_GETREV(device_get_parent(dev), atadev->unit) << 8); return 0; case IOCATASSPINDOWN: atadev->spindown = *mode; @@ -566,6 +748,7 @@ ata_device_ioctl(device_t dev, u_long cmd, caddr_t data) } } +#ifndef ATA_CAM static void ata_boot_attach(void) { @@ -590,11 +773,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 +793,7 @@ ata_add_child(device_t parent, struct ata_device *atadev, int unit) } return child; } +#endif int ata_getparam(struct ata_device *atadev, int init) @@ -705,6 +890,7 @@ ata_getparam(struct ata_device *atadev, int init) return error; } +#ifndef ATA_CAM int ata_identify(device_t dev) { @@ -778,6 +964,7 @@ ata_identify(device_t dev) mtx_unlock(&Giant); return 0; } +#endif void ata_default_registers(device_t dev) @@ -920,7 +1107,7 @@ ata_unit2str(struct ata_device *atadev) return str; } -char * +const char * ata_mode2str(int mode) { switch (mode) { @@ -950,6 +1137,18 @@ ata_mode2str(int mode) } } +const char * +ata_satarev2str(int rev) +{ + switch (rev) { + case 0: return ""; + case 1: return "SATA 1.5Gb/s"; + case 2: return "SATA 3Gb/s"; + case 3: return "SATA 6Gb/s"; + default: return "???"; + } +} + int ata_atapi(device_t dev) { @@ -1081,6 +1280,358 @@ 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 && + ch->curr[ccb->ccb_h.target_id].mode >= ATA_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, + ch->curr[ccb->ccb_h.target_id].bytecount); +// 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; + int fatalerr = 0; + + 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; + fatalerr = 1; + } 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); + /* Do error recovery if needed. */ + if (fatalerr) + ata_reinit(dev); +} + +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: + { + struct ccb_trans_settings *cts = &ccb->cts; + struct ata_cam_device *d; + + if (cts->type == CTS_TYPE_CURRENT_SETTINGS) + d = &ch->curr[ccb->ccb_h.target_id]; + else + d = &ch->user[ccb->ccb_h.target_id]; + if ((ch->flags & ATA_SATA) && (ch->flags & ATA_NO_SLAVE)) { + if (cts->xport_specific.sata.valid & CTS_SATA_VALID_REVISION) + d->revision = cts->xport_specific.sata.revision; + if (cts->xport_specific.ata.valid & CTS_SATA_VALID_MODE) { + if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { + d->mode = ATA_SETMODE(ch->dev, + ccb->ccb_h.target_id, + cts->xport_specific.sata.mode); + } else + d->mode = cts->xport_specific.sata.mode; + } + if (cts->xport_specific.ata.valid & CTS_SATA_VALID_BYTECOUNT) + d->bytecount = min(8192, cts->xport_specific.sata.bytecount); + } else { + if (cts->xport_specific.ata.valid & CTS_ATA_VALID_MODE) { + if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { + d->mode = ATA_SETMODE(ch->dev, + ccb->ccb_h.target_id, + cts->xport_specific.ata.mode); + } else + d->mode = cts->xport_specific.ata.mode; + } + if (cts->xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT) + d->bytecount = cts->xport_specific.ata.bytecount; + if (ch->flags & ATA_SATA) + d->bytecount = min(8192, d->bytecount); + } + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } + case XPT_GET_TRAN_SETTINGS: + { + struct ccb_trans_settings *cts = &ccb->cts; + struct ata_cam_device *d; + + if (cts->type == CTS_TYPE_CURRENT_SETTINGS) + d = &ch->curr[ccb->ccb_h.target_id]; + else + d = &ch->user[ccb->ccb_h.target_id]; + cts->protocol = PROTO_ATA; + cts->protocol_version = PROTO_VERSION_UNSPECIFIED; + if ((ch->flags & ATA_SATA) && (ch->flags & ATA_NO_SLAVE)) { + cts->transport = XPORT_SATA; + cts->transport_version = XPORT_VERSION_UNSPECIFIED; + cts->xport_specific.sata.mode = d->mode; + cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE; + cts->xport_specific.sata.bytecount = d->bytecount; + cts->xport_specific.sata.valid |= CTS_SATA_VALID_BYTECOUNT; + if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { + cts->xport_specific.sata.revision = + ATA_GETREV(dev, ccb->ccb_h.target_id); + } else + cts->xport_specific.sata.revision = d->revision; + cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION; + } else { + cts->transport = XPORT_ATA; + cts->transport_version = XPORT_VERSION_UNSPECIFIED; + cts->xport_specific.ata.mode = d->mode; + cts->xport_specific.ata.valid |= CTS_ATA_VALID_MODE; + cts->xport_specific.ata.bytecount = d->bytecount; + cts->xport_specific.ata.valid |= CTS_ATA_VALID_BYTECOUNT; + } + 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; + if (ch->flags & ATA_NO_SLAVE) + cpi->max_target = 0; + else + cpi->max_target = 1; + cpi->max_lun = 0; + cpi->initiator_id = 0; + cpi->bus_id = cam_sim_bus(sim); + if (ch->flags & ATA_SATA) + cpi->base_transfer_speed = 150000; + else + cpi->base_transfer_speed = 3300; + 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); + if ((ch->flags & ATA_SATA) && (ch->flags & ATA_NO_SLAVE)) + cpi->transport = XPORT_SATA; + else + 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 @@ -1088,10 +1639,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"); @@ -1109,11 +1663,14 @@ ata_module_event_handler(module_t mod, int what, void *arg) 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: @@ -1124,6 +1681,9 @@ ata_module_event_handler(module_t mod, int what, void *arg) static moduledata_t ata_moduledata = { "ata", ata_module_event_handler, NULL }; DECLARE_MODULE(ata, ata_moduledata, SI_SUB_CONFIGURE, SI_ORDER_SECOND); MODULE_VERSION(ata, 1); +#ifdef ATA_CAM +MODULE_DEPEND(ata, cam, 1, 1, 1); +#endif static void ata_init(void) diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index f832505f36b1..32f095ec4ee5 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -425,6 +425,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 */ @@ -531,6 +534,14 @@ struct ata_resource { int offset; }; +#ifdef ATA_CAM +struct ata_cam_device { + u_int revision; + int mode; + u_int bytecount; +}; +#endif + /* structure describing an ATA channel */ struct ata_channel { device_t dev; /* device handle */ @@ -547,6 +558,9 @@ struct ata_channel { #define ATA_ATAPI_DMA_RO 0x04 #define ATA_NO_48BIT_DMA 0x08 #define ATA_ALWAYS_DMASTAT 0x10 +#define ATA_CHECKS_CABLE 0x20 +#define ATA_NO_ATAPI_DMA 0x40 +#define ATA_SATA 0x80 int pm_level; /* power management level */ int devices; /* what is present */ @@ -567,6 +581,12 @@ 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; + struct ata_cam_device user[16]; /* User-specified settings */ + struct ata_cam_device curr[16]; /* Current settings */ +#endif }; /* disk bay/enclosure related */ @@ -600,12 +620,20 @@ void ata_default_registers(device_t dev); void ata_modify_if_48bit(struct ata_request *request); void ata_udelay(int interval); char *ata_unit2str(struct ata_device *atadev); -char *ata_mode2str(int mode); +const char *ata_mode2str(int mode); +const char *ata_satarev2str(int rev); int ata_atapi(device_t dev); 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); +void ata_setmode(device_t dev); +void ata_print_cable(device_t dev, u_int8_t *who); +int ata_check_80pin(device_t dev, int mode); +#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); @@ -635,7 +663,8 @@ void ata_sata_phy_check_events(device_t dev); int ata_sata_scr_read(struct ata_channel *ch, int port, int reg, uint32_t *val); int ata_sata_scr_write(struct ata_channel *ch, int port, int reg, uint32_t val); int ata_sata_phy_reset(device_t dev, int port, int quick); -void ata_sata_setmode(device_t dev, int mode); +int ata_sata_setmode(device_t dev, int target, int mode); +int ata_sata_getrev(device_t dev, int target); int ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis); void ata_pm_identify(device_t dev); diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index ea427e574ec4..0cd0a0f95c7e 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -385,7 +385,7 @@ ad_init(device_t dev) { struct ata_device *atadev = device_get_softc(dev); - ATA_SETMODE(device_get_parent(dev), dev); + ata_setmode(dev); /* enable readahead caching */ if (atadev->param.support.command1 & ATA_SUPPORT_LOOKAHEAD) @@ -537,12 +537,13 @@ ad_describe(device_t dev) strncpy(product, atadev->param.model, 40); } - device_printf(dev, "%juMB <%s%s %.8s> at ata%d-%s %s%s\n", + device_printf(dev, "%juMB <%s%s %.8s> at ata%d-%s %s%s %s\n", adp->total_secs / (1048576 / DEV_BSIZE), vendor, product, atadev->param.revision, device_get_unit(ch->dev), ata_unit2str(atadev), (adp->flags & AD_F_TAG_ENABLED) ? "tagged " : "", - ata_mode2str(atadev->mode)); + ata_mode2str(atadev->mode), + ata_satarev2str(ATA_GETREV(device_get_parent(dev), atadev->unit))); if (bootverbose) { device_printf(dev, "%ju sectors [%juC/%dH/%dS] " "%d sectors/interrupt %d depth queue\n", adp->total_secs, diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c index eae434833462..478693dd759c 100644 --- a/sys/dev/ata/ata-dma.c +++ b/sys/dev/ata/ata-dma.c @@ -76,7 +76,7 @@ ata_dmainit(device_t dev) ch->dma.alignment = 2; ch->dma.boundary = 65536; ch->dma.segsize = 65536; - ch->dma.max_iosize = 128 * DEV_BSIZE; + ch->dma.max_iosize = MIN((ATA_DMA_ENTRIES - 1) * PAGE_SIZE, MAXPHYS); ch->dma.max_address = BUS_SPACE_MAXADDR_32BIT; ch->dma.dma_slots = 1; diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c index 2dbb9862d0e1..566b8f676a59 100644 --- a/sys/dev/ata/ata-lowlevel.c +++ b/sys/dev/ata/ata-lowlevel.c @@ -82,6 +82,9 @@ ata_begin_transaction(struct ata_request *request) ATA_DEBUG_RQ(request, "begin transaction"); /* disable ATAPI DMA writes if HW doesn't support it */ + if ((ch->flags & ATA_NO_ATAPI_DMA) && + (request->flags & ATA_R_ATAPI) == ATA_R_ATAPI) + request->flags &= ~ATA_R_DMA; if ((ch->flags & ATA_ATAPI_DMA_RO) && ((request->flags & (ATA_R_ATAPI | ATA_R_DMA | ATA_R_WRITE)) == (ATA_R_ATAPI | ATA_R_DMA | ATA_R_WRITE))) @@ -757,7 +760,9 @@ 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 (request->flags & ATA_R_48BIT) { ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature >> 8); @@ -775,6 +780,7 @@ ata_tf_write(struct ata_request *request) 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; @@ -797,13 +803,16 @@ ata_tf_write(struct ata_request *request) 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 } } diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c index ce21926cb3ed..cd877284085f 100644 --- a/sys/dev/ata/ata-pci.c +++ b/sys/dev/ata/ata-pci.c @@ -55,10 +55,6 @@ static MALLOC_DEFINE(M_ATAPCI, "ata_pci", "ATA driver PCI"); /* misc defines */ #define IOMASK 0xfffffffc -/* local prototypes */ -static int ata_generic_chipinit(device_t dev); -static void ata_generic_setmode(device_t dev, int mode); - /* * generic PCI ATA device probe */ @@ -374,18 +370,14 @@ ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, } } -static void -ata_generic_setmode(device_t dev, int mode) +int +ata_generic_setmode(device_t dev, int target, int mode) { - struct ata_device *atadev = device_get_softc(dev); - mode = ata_limit_mode(dev, mode, ATA_UDMA2); - mode = ata_check_80pin(dev, mode); - if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) - atadev->mode = mode; + return (min(mode, ATA_UDMA2)); } -static int +int ata_generic_chipinit(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(dev); @@ -707,16 +699,26 @@ ata_pcichannel_reset(device_t dev) ata_generic_reset(dev); } -static void -ata_pcichannel_setmode(device_t parent, device_t dev) +static int +ata_pcichannel_setmode(device_t dev, int target, int mode) { - struct ata_pci_controller *ctlr = device_get_softc(GRANDPARENT(dev)); - struct ata_device *atadev = device_get_softc(dev); - int mode = atadev->mode; + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - ctlr->setmode(dev, ATA_PIO_MAX); - if (mode >= ATA_DMA) - ctlr->setmode(dev, mode); + if (ctlr->setmode) + return (ctlr->setmode(dev, target, mode)); + else + return (ata_generic_setmode(dev, target, mode)); +} + +static int +ata_pcichannel_getrev(device_t dev, int target) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + + if (ctlr->getrev) + return (ctlr->getrev(dev, target)); + else + return (0); } static device_method_t ata_pcichannel_methods[] = { @@ -730,6 +732,7 @@ static device_method_t ata_pcichannel_methods[] = { /* ATA methods */ DEVMETHOD(ata_setmode, ata_pcichannel_setmode), + DEVMETHOD(ata_getrev, ata_pcichannel_getrev), DEVMETHOD(ata_locking, ata_pcichannel_locking), DEVMETHOD(ata_reset, ata_pcichannel_reset), @@ -858,31 +861,6 @@ ata_find_chip(device_t dev, struct ata_chip_id *index, int slot) return (NULL); } -void -ata_print_cable(device_t dev, u_int8_t *who) -{ - device_printf(dev, - "DMA limited to UDMA33, %s found non-ATA66 cable\n", who); -} - -int -ata_check_80pin(device_t dev, int mode) -{ - struct ata_device *atadev = device_get_softc(dev); - - if (!ata_dma_check_80pin) { - if (bootverbose) - device_printf(dev, "Skipping 80pin cable check\n"); - return mode; - } - - if (mode > ATA_UDMA2 && !(atadev->param.hwres & ATA_CABLE_ID)) { - ata_print_cable(dev, "device"); - mode = ATA_UDMA2; - } - return mode; -} - char * ata_pcivendor2str(device_t dev) { diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h index f2a0e1371ffa..7bfb7a259909 100644 --- a/sys/dev/ata/ata-pci.h +++ b/sys/dev/ata/ata-pci.h @@ -63,7 +63,8 @@ struct ata_pci_controller { int (*ch_resume)(device_t); int (*locking)(device_t, int); void (*reset)(device_t); - void (*setmode)(device_t, int); + int (*setmode)(device_t, int, int); + int (*getrev)(device_t, int); struct { void (*function)(void *); void *argument; @@ -506,12 +507,12 @@ void ata_pci_dmafini(device_t dev); char *ata_pcivendor2str(device_t dev); int ata_legacy(device_t); void ata_generic_intr(void *data); +int ata_generic_chipinit(device_t dev); +int ata_generic_setmode(device_t dev, int target, int mode); int ata_setup_interrupt(device_t dev, void *intr_func); void ata_set_desc(device_t dev); struct ata_chip_id *ata_match_chip(device_t dev, struct ata_chip_id *index); struct ata_chip_id *ata_find_chip(device_t dev, struct ata_chip_id *index, int slot); -void ata_print_cable(device_t dev, u_int8_t *who); -int ata_check_80pin(device_t dev, int mode); int ata_mode2idx(int mode); /* global prototypes from chipsets/ata-*.c */ diff --git a/sys/dev/ata/ata-queue.c b/sys/dev/ata/ata-queue.c index c0487787144c..a3b1c4e4435c 100644 --- a/sys/dev/ata/ata-queue.c +++ b/sys/dev/ata/ata-queue.c @@ -511,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 --git a/sys/dev/ata/ata-sata.c b/sys/dev/ata/ata-sata.c index 5f5daa48f3f4..9e3f7e8de06d 100644 --- a/sys/dev/ata/ata-sata.c +++ b/sys/dev/ata/ata-sata.c @@ -209,38 +209,21 @@ ata_sata_phy_reset(device_t dev, int port, int quick) return 0; } -void -ata_sata_setmode(device_t dev, int mode) +int +ata_sata_setmode(device_t dev, int target, int mode) { - struct ata_device *atadev = device_get_softc(dev); - /* - * if we detect that the device isn't a real SATA device we limit - * the transfer mode to UDMA5/ATA100. - * this works around the problems some devices has with the - * Marvell 88SX8030 SATA->PATA converters and UDMA6/ATA133. - */ - if (atadev->param.satacapabilities != 0x0000 && - atadev->param.satacapabilities != 0xffff) { - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + return (min(mode, ATA_UDMA5)); +} - /* on some drives we need to set the transfer mode */ - ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, - ata_limit_mode(dev, mode, ATA_UDMA6)); +int +ata_sata_getrev(device_t dev, int target) +{ + struct ata_channel *ch = device_get_softc(dev); - /* query SATA STATUS for the speed */ - if (ch->r_io[ATA_SSTATUS].res && - ((ATA_IDX_INL(ch, ATA_SSTATUS) & ATA_SS_CONWELL_MASK) == - ATA_SS_CONWELL_GEN2)) - atadev->mode = ATA_SA300; - else - atadev->mode = ATA_SA150; - } - else { - mode = ata_limit_mode(dev, mode, ATA_UDMA5); - if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) - atadev->mode = mode; - } + if (ch->r_io[ATA_SSTATUS].res) + return ((ATA_IDX_INL(ch, ATA_SSTATUS) & 0x0f0) >> 4); + return (0); } int diff --git a/sys/dev/ata/ata_if.m b/sys/dev/ata/ata_if.m index 8fcc3f267592..a1775ac6ee71 100644 --- a/sys/dev/ata/ata_if.m +++ b/sys/dev/ata/ata_if.m @@ -57,17 +57,24 @@ HEADER { }; CODE { - static void ata_null_setmode(device_t parent, device_t dev) + static int ata_null_setmode(device_t dev, int target, int mode) { - struct ata_device *atadev = device_get_softc(dev); - atadev->mode = ata_limit_mode(dev, atadev->mode, ATA_PIO_MAX); + if (mode > ATA_PIO_MAX) + return (ATA_PIO_MAX); + return (mode); } }; -METHOD void setmode { - device_t channel; +METHOD int setmode { device_t dev; -} DEFAULT ata_null_setmode;; + int target; + int mode; +} DEFAULT ata_null_setmode; + +METHOD int getrev { + device_t dev; + int target; +}; METHOD void reset { device_t channel; diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c index a021e005492d..5d0c0f704760 100644 --- a/sys/dev/ata/atapi-cd.c +++ b/sys/dev/ata/atapi-cd.c @@ -126,7 +126,7 @@ acd_attach(device_t dev) } cdp->block_size = 2048; device_set_ivars(dev, cdp); - ATA_SETMODE(device_get_parent(dev), dev); + ata_setmode(dev); ata_controlcmd(dev, ATA_DEVICE_RESET, 0, 0, 0); acd_get_cap(dev); g_post_event(acd_geom_attach, dev, M_WAITOK, NULL); @@ -163,7 +163,7 @@ acd_reinit(device_t dev) if (!(ch->devices & (ATA_ATAPI_MASTER << atadev->unit))) return 1; - ATA_SETMODE(device_get_parent(dev), dev); + ata_setmode(dev); return 0; } @@ -1724,7 +1724,8 @@ acd_describe(device_t dev) printf("%s %dKB buffer", comma ? "," : "", cdp->cap.buf_size); comma = 1; } - printf("%s %s\n", comma ? "," : "", ata_mode2str(atadev->mode)); + printf("%s %s %s\n", comma ? "," : "", ata_mode2str(atadev->mode), + ata_satarev2str(ATA_GETREV(device_get_parent(dev), atadev->unit))); device_printf(dev, "Reads:"); comma = 0; @@ -1874,10 +1875,11 @@ acd_describe(device_t dev) "CDROM"); if (cdp->changer_info) printf("with %d CD changer ", cdp->changer_info->slots); - printf("<%.40s/%.8s> at ata%d-%s %s\n", + printf("<%.40s/%.8s> at ata%d-%s %s %s\n", atadev->param.model, atadev->param.revision, device_get_unit(ch->dev), ata_unit2str(atadev), - ata_mode2str(atadev->mode) ); + ata_mode2str(atadev->mode), + ata_satarev2str(ATA_GETREV(device_get_parent(dev), atadev->unit))); } } diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c index 5baeab9a7ee5..5572d1c27947 100644 --- a/sys/dev/ata/atapi-fd.c +++ b/sys/dev/ata/atapi-fd.c @@ -85,7 +85,7 @@ afd_attach(device_t dev) return ENOMEM; } device_set_ivars(dev, fdp); - ATA_SETMODE(device_get_parent(dev), dev); + ata_setmode(dev); if (afd_sense(dev)) { device_set_ivars(dev, NULL); @@ -152,7 +152,7 @@ afd_reinit(device_t dev) if (!(ch->devices & (ATA_ATAPI_MASTER << atadev->unit))) return 1; - ATA_SETMODE(device_get_parent(dev), dev); + ata_setmode(dev); return 0; } @@ -400,10 +400,11 @@ afd_describe(device_t dev) else strcpy(sizestring, "(no media)"); - device_printf(dev, "%s <%.40s %.8s> at ata%d-%s %s\n", + device_printf(dev, "%s <%.40s %.8s> at ata%d-%s %s %s\n", sizestring, atadev->param.model, atadev->param.revision, device_get_unit(ch->dev), ata_unit2str(atadev), - ata_mode2str(atadev->mode)); + ata_mode2str(atadev->mode), + ata_satarev2str(ATA_GETREV(device_get_parent(dev), atadev->unit))); if (bootverbose) { device_printf(dev, "%ju sectors [%juC/%dH/%dS]\n", fdp->mediasize / fdp->sectorsize, diff --git a/sys/dev/ata/atapi-tape.c b/sys/dev/ata/atapi-tape.c index 5b4da81dc1bd..b6ca4ad6e683 100644 --- a/sys/dev/ata/atapi-tape.c +++ b/sys/dev/ata/atapi-tape.c @@ -111,7 +111,7 @@ ast_attach(device_t dev) return ENOMEM; } device_set_ivars(dev, stp); - ATA_SETMODE(device_get_parent(dev), dev); + ata_setmode(dev); if (ast_sense(dev)) { device_set_ivars(dev, NULL); @@ -193,7 +193,7 @@ ast_reinit(device_t dev) if (!(ch->devices & (ATA_ATAPI_MASTER << atadev->unit))) return 1; - ATA_SETMODE(device_get_parent(dev), dev); + ata_setmode(dev); return 0; } @@ -673,7 +673,8 @@ ast_describe(device_t dev) printf("transfer limit %d blk%s, ", stp->cap.ctl, (stp->cap.ctl > 1) ? "s" : ""); printf("%dKB buffer, ", (stp->cap.buffer_size * DEV_BSIZE) / 1024); - printf("%s\n", ata_mode2str(atadev->mode)); + printf("%s %s\n", ata_mode2str(atadev->mode), + ata_satarev2str(ATA_GETREV(device_get_parent(dev), atadev->unit))); device_printf(dev, "Medium: "); switch (stp->cap.medium_type) { case 0x00: @@ -704,10 +705,11 @@ ast_describe(device_t dev) printf("\n"); } else { - device_printf(dev, "TAPE <%.40s/%.8s> at ata%d-%s %s\n", + device_printf(dev, "TAPE <%.40s/%.8s> at ata%d-%s %s %s\n", atadev->param.model, atadev->param.revision, device_get_unit(ch->dev), ata_unit2str(atadev), - ata_mode2str(atadev->mode)); + ata_mode2str(atadev->mode), + ata_satarev2str(ATA_GETREV(device_get_parent(dev), atadev->unit))); } } diff --git a/sys/dev/ata/chipsets/ata-acard.c b/sys/dev/ata/chipsets/ata-acard.c index c52c2cbc0883..bb81c48dc4cf 100644 --- a/sys/dev/ata/chipsets/ata-acard.c +++ b/sys/dev/ata/chipsets/ata-acard.c @@ -61,8 +61,8 @@ struct ata_serialize { static int ata_acard_chipinit(device_t dev); static int ata_acard_ch_attach(device_t dev); static int ata_acard_status(device_t dev); -static void ata_acard_850_setmode(device_t dev, int mode); -static void ata_acard_86X_setmode(device_t dev, int mode); +static int ata_acard_850_setmode(device_t dev, int target, int mode); +static int ata_acard_86X_setmode(device_t dev, int target, int mode); static int ata_serialize(device_t dev, int flags); static void ata_serialize_init(struct ata_serialize *serial); @@ -130,6 +130,7 @@ ata_acard_ch_attach(device_t dev) return ENXIO; ch->hw.status = ata_acard_status; + ch->flags |= ATA_NO_ATAPI_DMA; return 0; } @@ -162,79 +163,52 @@ ata_acard_status(device_t dev) return 1; } -static void -ata_acard_850_setmode(device_t dev, int mode) +static int +ata_acard_850_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; - - mode = ata_limit_mode(dev, mode, - ata_atapi(dev) ? ATA_PIO_MAX : ctlr->chip->max_dma); + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; + mode = min(mode, ctlr->chip->max_dma); /* XXX SOS missing WDMA0+1 + PIO modes */ if (mode >= ATA_WDMA2) { - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { - u_int8_t reg54 = pci_read_config(gparent, 0x54, 1); + u_int8_t reg54 = pci_read_config(parent, 0x54, 1); reg54 &= ~(0x03 << (devno << 1)); if (mode >= ATA_UDMA0) reg54 |= (((mode & ATA_MODE_MASK) + 1) << (devno << 1)); - pci_write_config(gparent, 0x54, reg54, 1); - pci_write_config(gparent, 0x4a, 0xa6, 1); - pci_write_config(gparent, 0x40 + (devno << 1), 0x0301, 2); - atadev->mode = mode; - return; - } + pci_write_config(parent, 0x54, reg54, 1); + pci_write_config(parent, 0x4a, 0xa6, 1); + pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2); } /* we could set PIO mode timings, but we assume the BIOS did that */ + return (mode); } -static void -ata_acard_86X_setmode(device_t dev, int mode) +static int +ata_acard_86X_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; - - mode = ata_limit_mode(dev, mode, - ata_atapi(dev) ? ATA_PIO_MAX : ctlr->chip->max_dma); - - mode = ata_check_80pin(dev, mode); - - /* XXX SOS missing WDMA0+1 + PIO modes */ - if (mode >= ATA_WDMA2) { - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { - u_int16_t reg44 = pci_read_config(gparent, 0x44, 2); + mode = min(mode, ctlr->chip->max_dma); + /* XXX SOS missing WDMA0+1 + PIO modes */ + if (mode >= ATA_WDMA2) { + u_int16_t reg44 = pci_read_config(parent, 0x44, 2); - reg44 &= ~(0x000f << (devno << 2)); - if (mode >= ATA_UDMA0) - reg44 |= (((mode & ATA_MODE_MASK) + 1) << (devno << 2)); - pci_write_config(gparent, 0x44, reg44, 2); - pci_write_config(gparent, 0x4a, 0xa6, 1); - pci_write_config(gparent, 0x40 + devno, 0x31, 1); - atadev->mode = mode; - return; + reg44 &= ~(0x000f << (devno << 2)); + if (mode >= ATA_UDMA0) + reg44 |= (((mode & ATA_MODE_MASK) + 1) << (devno << 2)); + pci_write_config(parent, 0x44, reg44, 2); + pci_write_config(parent, 0x4a, 0xa6, 1); + pci_write_config(parent, 0x40 + devno, 0x31, 1); } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ + /* we could set PIO mode timings, but we assume the BIOS did that */ + return (mode); } static void diff --git a/sys/dev/ata/chipsets/ata-acerlabs.c b/sys/dev/ata/chipsets/ata-acerlabs.c index cf503c591b2d..e74b2105f417 100644 --- a/sys/dev/ata/chipsets/ata-acerlabs.c +++ b/sys/dev/ata/chipsets/ata-acerlabs.c @@ -56,7 +56,7 @@ static int ata_ali_chipinit(device_t dev); static int ata_ali_ch_attach(device_t dev); static int ata_ali_sata_ch_attach(device_t dev); static void ata_ali_reset(device_t dev); -static void ata_ali_setmode(device_t dev, int mode); +static int ata_ali_setmode(device_t dev, int target, int mode); /* misc defines */ #define ALI_OLD 0x01 @@ -113,6 +113,7 @@ ata_ali_chipinit(device_t dev) ctlr->ch_attach = ata_ali_sata_ch_attach; ctlr->ch_detach = ata_pci_ch_detach; ctlr->setmode = ata_sata_setmode; + ctlr->getrev = ata_sata_getrev; /* AHCI mode is correctly supported only on the ALi 5288. */ if ((ctlr->chip->chipid == ATA_ALI_5288) && @@ -176,6 +177,7 @@ ata_ali_ch_attach(device_t dev) if (ata_pci_ch_attach(dev)) return ENXIO; + ch->flags |= ATA_CHECKS_CABLE; /* older chips can't do 48bit DMA transfers */ if (ctlr->chip->chiprev <= 0xc4) ch->flags |= ATA_NO_48BIT_DMA; @@ -218,6 +220,7 @@ ata_ali_sata_ch_attach(device_t dev) } } ch->flags |= ATA_NO_SLAVE; + ch->flags |= ATA_SATA; /* XXX SOS PHY handling awkward in ALI chip not supported yet */ ata_pci_hw(dev); @@ -257,67 +260,56 @@ ata_ali_reset(device_t dev) } } -static void -ata_ali_setmode(device_t dev, int mode) +static int +ata_ali_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; + int piomode; + u_int32_t piotimings[] = + { 0x006d0003, 0x00580002, 0x00440001, 0x00330001, + 0x00310001, 0x006d0003, 0x00330001, 0x00310001 }; + u_int8_t udma[] = {0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x0f, 0x0d}; + u_int32_t word54; - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); + mode = min(mode, ctlr->chip->max_dma); - if (ctlr->chip->cfg2 & ALI_NEW) { - if (mode > ATA_UDMA2 && - pci_read_config(gparent, 0x4a, 1) & (1 << ch->unit)) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; + if (ctlr->chip->cfg2 & ALI_NEW) { + if (mode > ATA_UDMA2 && + pci_read_config(parent, 0x4a, 1) & (1 << ch->unit)) { + ata_print_cable(dev, "controller"); + mode = ATA_UDMA2; + } } - } - else - mode = ata_check_80pin(dev, mode); - - if (ctlr->chip->cfg2 & ALI_OLD) { - /* doesn't support ATAPI DMA on write */ - ch->flags |= ATA_ATAPI_DMA_RO; - if (ch->devices & ATA_ATAPI_MASTER && ch->devices & ATA_ATAPI_SLAVE) { - /* doesn't support ATAPI DMA on two ATAPI devices */ - device_printf(dev, "two atapi devices on this channel, no DMA\n"); - mode = ata_limit_mode(dev, mode, ATA_PIO_MAX); + if (ctlr->chip->cfg2 & ALI_OLD) { + /* doesn't support ATAPI DMA on write */ + ch->flags |= ATA_ATAPI_DMA_RO; + if (ch->devices & ATA_ATAPI_MASTER && + ch->devices & ATA_ATAPI_SLAVE) { + /* doesn't support ATAPI DMA on two ATAPI devices */ + device_printf(dev, "two atapi devices on this channel," + " no DMA\n"); + mode = min(mode, ATA_PIO_MAX); + } } - } - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { + /* Set UDMA mode */ + word54 = pci_read_config(parent, 0x54, 4); if (mode >= ATA_UDMA0) { - u_int8_t udma[] = {0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x0f, 0x0d}; - u_int32_t word54 = pci_read_config(gparent, 0x54, 4); - word54 &= ~(0x000f000f << (devno << 2)); word54 |= (((udma[mode&ATA_MODE_MASK]<<16)|0x05)<<(devno<<2)); - pci_write_config(gparent, 0x54, word54, 4); - pci_write_config(gparent, 0x58 + (ch->unit << 2), - 0x00310001, 4); + piomode = ATA_PIO4; } else { - u_int32_t piotimings[] = - { 0x006d0003, 0x00580002, 0x00440001, 0x00330001, - 0x00310001, 0x00440001, 0x00330001, 0x00310001}; - - pci_write_config(gparent, 0x54, pci_read_config(gparent, 0x54, 4) & - ~(0x0008000f << (devno << 2)), 4); - pci_write_config(gparent, 0x58 + (ch->unit << 2), - piotimings[ata_mode2idx(mode)], 4); + word54 &= ~(0x0008000f << (devno << 2)); + piomode = mode; } - atadev->mode = mode; - } + pci_write_config(parent, 0x54, word54, 4); + /* Set PIO/WDMA mode */ + pci_write_config(parent, 0x58 + (ch->unit << 2), + piotimings[ata_mode2idx(piomode)], 4); + return (mode); } ATA_DECLARE_DRIVER(ata_ali); diff --git a/sys/dev/ata/chipsets/ata-ahci.c b/sys/dev/ata/chipsets/ata-ahci.c index e4a7cd165ad4..39c51523e763 100644 --- a/sys/dev/ata/chipsets/ata-ahci.c +++ b/sys/dev/ata/chipsets/ata-ahci.c @@ -194,6 +194,7 @@ ata_ahci_chipinit(device_t dev) ctlr->ch_suspend = ata_ahci_ch_suspend; ctlr->ch_resume = ata_ahci_ch_resume; ctlr->setmode = ata_sata_setmode; + ctlr->getrev = ata_sata_getrev; ctlr->suspend = ata_ahci_suspend; ctlr->resume = ata_ahci_ctlr_reset; @@ -309,6 +310,8 @@ ata_ahci_ch_attach(device_t dev) ch->hw.softreset = ata_ahci_softreset; ch->hw.pm_read = ata_ahci_pm_read; ch->hw.pm_write = ata_ahci_pm_write; + ch->flags |= ATA_NO_SLAVE; + ch->flags |= ATA_SATA; ata_ahci_ch_resume(dev); return 0; diff --git a/sys/dev/ata/chipsets/ata-amd.c b/sys/dev/ata/chipsets/ata-amd.c index 9c14e99cba4c..1cf9ac073c4f 100644 --- a/sys/dev/ata/chipsets/ata-amd.c +++ b/sys/dev/ata/chipsets/ata-amd.c @@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$"); /* local prototypes */ static int ata_amd_chipinit(device_t dev); -static void ata_amd_setmode(device_t dev, int mode); +static int ata_amd_setmode(device_t dev, int target, int mode); /* misc defines */ #define AMD_BUG 0x01 @@ -104,46 +104,37 @@ ata_amd_chipinit(device_t dev) return 0; } -static void -ata_amd_setmode(device_t dev, int mode) +static int +ata_amd_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - u_int8_t timings[] = { 0xa8, 0x65, 0x42, 0x22, 0x20, 0x42, 0x22, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; - int modes[7] = { 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 0xc7 }; - int devno = (ch->unit << 1) + atadev->unit; - int reg = 0x53 - devno; - int error; + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; + int piomode; + u_int8_t timings[] = { 0xa8, 0x65, 0x42, 0x22, 0x20, 0xa8, 0x22, 0x20 }; + int modes[7] = { 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 0xc7 }; + int reg = 0x53 - devno; - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - if (ctlr->chip->cfg1 & AMD_CABLE) { - if (mode > ATA_UDMA2 && - !(pci_read_config(gparent, 0x42, 1) & (1 << devno))) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; + mode = min(mode, ctlr->chip->max_dma); + if (ctlr->chip->cfg1 & AMD_CABLE) { + if (mode > ATA_UDMA2 && + !(pci_read_config(parent, 0x42, 1) & (1 << devno))) { + ata_print_cable(dev, "controller"); + mode = ATA_UDMA2; + } } - } - else - mode = ata_check_80pin(dev, mode); - - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", ata_mode2str(mode), - ctlr->chip->text); - if (!error) { - pci_write_config(gparent, reg - 0x08, timings[ata_mode2idx(mode)], 1); - if (mode >= ATA_UDMA0) - pci_write_config(gparent, reg, modes[mode & ATA_MODE_MASK], 1); - else - pci_write_config(gparent, reg, 0x8b, 1); - atadev->mode = mode; - } + /* Set UDMA timings. */ + if (mode >= ATA_UDMA0) { + pci_write_config(parent, reg, modes[mode & ATA_MODE_MASK], 1); + piomode = ATA_PIO4; + } else { + pci_write_config(parent, reg, 0x8b, 1); + piomode = mode; + } + /* Set WDMA/PIO timings. */ + pci_write_config(parent, reg - 0x08, timings[ata_mode2idx(piomode)], 1); + return (mode); } ATA_DECLARE_DRIVER(ata_amd); diff --git a/sys/dev/ata/chipsets/ata-ati.c b/sys/dev/ata/chipsets/ata-ati.c index 4436c7f53c96..d464897243df 100644 --- a/sys/dev/ata/chipsets/ata-ati.c +++ b/sys/dev/ata/chipsets/ata-ati.c @@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$"); /* local prototypes */ static int ata_ati_chipinit(device_t dev); -static void ata_ati_setmode(device_t dev, int mode); +static int ata_ati_setmode(device_t dev, int target, int mode); /* misc defines */ #define ATI_PATA 0x01 @@ -160,68 +160,61 @@ ata_ati_chipinit(device_t dev) return 0; } -static void -ata_ati_setmode(device_t dev, int mode) +static int +ata_ati_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int offset = (devno ^ 0x01) << 3; - int error; - u_int8_t piotimings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20, 0x34, 0x22, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; - u_int8_t dmatimings[] = { 0x77, 0x21, 0x20 }; + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; + int offset = (devno ^ 0x01) << 3; + int piomode; + u_int8_t piotimings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 }; + u_int8_t dmatimings[] = { 0x77, 0x21, 0x20 }; - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - mode = ata_check_80pin(dev, mode); - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { + mode = min(mode, ctlr->chip->max_dma); if (mode >= ATA_UDMA0) { - pci_write_config(gparent, 0x56, - (pci_read_config(gparent, 0x56, 2) & + /* Set UDMA mode, enable UDMA, set WDMA2/PIO4 */ + pci_write_config(parent, 0x56, + (pci_read_config(parent, 0x56, 2) & ~(0xf << (devno << 2))) | ((mode & ATA_MODE_MASK) << (devno << 2)), 2); - pci_write_config(gparent, 0x54, - pci_read_config(gparent, 0x54, 1) | + pci_write_config(parent, 0x54, + pci_read_config(parent, 0x54, 1) | (0x01 << devno), 1); - pci_write_config(gparent, 0x44, - (pci_read_config(gparent, 0x44, 4) & + pci_write_config(parent, 0x44, + (pci_read_config(parent, 0x44, 4) & ~(0xff << offset)) | (dmatimings[2] << offset), 4); - } - else if (mode >= ATA_WDMA0) { - pci_write_config(gparent, 0x54, - pci_read_config(gparent, 0x54, 1) & + piomode = ATA_PIO4; + } else if (mode >= ATA_WDMA0) { + /* Disable UDMA, set WDMA mode and timings, calculate PIO. */ + pci_write_config(parent, 0x54, + pci_read_config(parent, 0x54, 1) & ~(0x01 << devno), 1); - pci_write_config(gparent, 0x44, - (pci_read_config(gparent, 0x44, 4) & + pci_write_config(parent, 0x44, + (pci_read_config(parent, 0x44, 4) & ~(0xff << offset)) | (dmatimings[mode & ATA_MODE_MASK] << offset), 4); - } - else - pci_write_config(gparent, 0x54, - pci_read_config(gparent, 0x54, 1) & + piomode = (mode == ATA_WDMA0) ? ATA_PIO0 : + (mode == ATA_WDMA1) ? ATA_PIO3 : ATA_PIO4; + } else { + /* Disable UDMA, set requested PIO. */ + pci_write_config(parent, 0x54, + pci_read_config(parent, 0x54, 1) & ~(0x01 << devno), 1); - - pci_write_config(gparent, 0x4a, - (pci_read_config(gparent, 0x4a, 2) & + piomode = mode; + } + /* Set PIO mode and timings, calculated above. */ + pci_write_config(parent, 0x4a, + (pci_read_config(parent, 0x4a, 2) & ~(0xf << (devno << 2))) | - (((mode - ATA_PIO0) & ATA_MODE_MASK) << (devno<<2)),2); - pci_write_config(gparent, 0x40, - (pci_read_config(gparent, 0x40, 4) & + ((piomode - ATA_PIO0) << (devno<<2)),2); + pci_write_config(parent, 0x40, + (pci_read_config(parent, 0x40, 4) & ~(0xff << offset)) | - (piotimings[ata_mode2idx(mode)] << offset), 4); - atadev->mode = mode; - } + (piotimings[ata_mode2idx(piomode)] << offset), 4); + return (mode); } ATA_DECLARE_DRIVER(ata_ati); diff --git a/sys/dev/ata/chipsets/ata-cenatek.c b/sys/dev/ata/chipsets/ata-cenatek.c index 8f6474cc57ab..cc54d2bbc20a 100644 --- a/sys/dev/ata/chipsets/ata-cenatek.c +++ b/sys/dev/ata/chipsets/ata-cenatek.c @@ -51,11 +51,6 @@ __FBSDID("$FreeBSD$"); #include #include -/* local prototypes */ -static int ata_cenatek_chipinit(device_t dev); -static void ata_cenatek_setmode(device_t dev, int mode); - - /* * Cenatek chipset support functions */ @@ -67,32 +62,9 @@ ata_cenatek_probe(device_t dev) if (pci_get_devid(dev) != ATA_CENATEK_ROCKET) return ENXIO; - ctlr->chipinit = ata_cenatek_chipinit; + ctlr->chipinit = ata_generic_chipinit; device_set_desc(dev, "Cenatek Rocket Drive controller"); return (BUS_PROBE_DEFAULT); } -static int -ata_cenatek_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev, ata_generic_intr)) - return ENXIO; - - ctlr->setmode = ata_cenatek_setmode; - return 0; -} - -static void -ata_cenatek_setmode(device_t dev, int mode) -{ - struct ata_device *atadev = device_get_softc(dev); - - mode = ata_limit_mode(dev, mode, ATA_UDMA2); - mode = ata_check_80pin(dev, mode); - if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) - atadev->mode = mode; -} - ATA_DECLARE_DRIVER(ata_cenatek); diff --git a/sys/dev/ata/chipsets/ata-cypress.c b/sys/dev/ata/chipsets/ata-cypress.c index ffa9782fa8b6..e4c1a93d0347 100644 --- a/sys/dev/ata/chipsets/ata-cypress.c +++ b/sys/dev/ata/chipsets/ata-cypress.c @@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$"); /* local prototypes */ static int ata_cypress_chipinit(device_t dev); -static void ata_cypress_setmode(device_t dev, int mode); +static int ata_cypress_setmode(device_t dev, int target, int mode); /* @@ -93,29 +93,20 @@ ata_cypress_chipinit(device_t dev) return 0; } -static void -ata_cypress_setmode(device_t dev, int mode) +static int +ata_cypress_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int error; + device_t parent = device_get_parent(dev); + struct ata_channel *ch = device_get_softc(dev); - mode = ata_limit_mode(dev, mode, ATA_WDMA2); + mode = min(mode, ATA_WDMA2); - /* XXX SOS missing WDMA0+1 + PIO modes */ - if (mode == ATA_WDMA2) { - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - if (bootverbose) - device_printf(dev, "%ssetting WDMA2 on Cypress chip\n", - error ? "FAILURE " : ""); - if (!error) { - pci_write_config(gparent, ch->unit ? 0x4e : 0x4c, 0x2020, 2); - atadev->mode = mode; - return; + /* XXX SOS missing WDMA0+1 + PIO modes */ + if (mode == ATA_WDMA2) { + pci_write_config(parent, ch->unit ? 0x4e : 0x4c, 0x2020, 2); } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ + /* we could set PIO mode timings, but we assume the BIOS did that */ + return (mode); } ATA_DECLARE_DRIVER(ata_cypress); diff --git a/sys/dev/ata/chipsets/ata-cyrix.c b/sys/dev/ata/chipsets/ata-cyrix.c index ddfa56245b7b..5a008562147d 100644 --- a/sys/dev/ata/chipsets/ata-cyrix.c +++ b/sys/dev/ata/chipsets/ata-cyrix.c @@ -53,7 +53,8 @@ __FBSDID("$FreeBSD$"); /* local prototypes */ static int ata_cyrix_chipinit(device_t dev); -static void ata_cyrix_setmode(device_t dev, int mode); +static int ata_cyrix_ch_attach(device_t dev); +static int ata_cyrix_setmode(device_t dev, int target, int mode); /* @@ -79,53 +80,57 @@ ata_cyrix_chipinit(device_t dev) if (ata_setup_interrupt(dev, ata_generic_intr)) return ENXIO; - + ctlr->ch_attach = ata_cyrix_ch_attach; ctlr->setmode = ata_cyrix_setmode; return 0; } -static void -ata_cyrix_setmode(device_t dev, int mode) +static int +ata_cyrix_ch_attach(device_t dev) { - struct ata_pci_controller *ctlr = device_get_softc(GRANDPARENT(dev)); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - u_int32_t piotiming[] = - { 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 }; - u_int32_t dmatiming[] = { 0x00077771, 0x00012121, 0x00002020 }; - u_int32_t udmatiming[] = { 0x00921250, 0x00911140, 0x00911030 }; - int error; + struct ata_channel *ch = device_get_softc(dev); + int error; + + error = ata_pci_ch_attach(dev); + ch->dma.alignment = 16; + ch->dma.max_iosize = 64 * DEV_BSIZE; + return (error); +} - mode = ata_limit_mode(dev, mode, ATA_UDMA2); - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); +static int +ata_cyrix_setmode(device_t dev, int target, int mode) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; + int piomode; + u_int32_t piotiming[] = + { 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 }; + u_int32_t dmatiming[] = { 0x00077771, 0x00012121, 0x00002020 }; + u_int32_t udmatiming[] = { 0x00921250, 0x00911140, 0x00911030 }; - if (bootverbose) - device_printf(dev, "%ssetting %s on Cyrix chip\n", - (error) ? "FAILURE " : "", ata_mode2str(mode)); - - if (!error) { + mode = min(mode, ATA_UDMA2); /* dont try to set the mode if we dont have the resource */ if (ctlr->r_res1) { - ch->dma.alignment = 16; - ch->dma.max_iosize = 64 * DEV_BSIZE; - - if (mode >= ATA_UDMA0) { + if (mode >= ATA_UDMA0) { + /* Set UDMA timings, and PIO4. */ + ATA_OUTL(ch->r_io[ATA_BMCMD_PORT].res, + 0x24 + (devno << 3), udmatiming[mode & ATA_MODE_MASK]); + piomode = ATA_PIO4; + } else if (mode >= ATA_WDMA0) { + /* Set WDMA timings, and respective PIO mode. */ + ATA_OUTL(ch->r_io[ATA_BMCMD_PORT].res, + 0x24 + (devno << 3), dmatiming[mode & ATA_MODE_MASK]); + piomode = (mode == ATA_WDMA0) ? ATA_PIO0 : + (mode == ATA_WDMA1) ? ATA_PIO3 : ATA_PIO4; + } else + piomode = mode; + /* Set PIO mode calculated above. */ ATA_OUTL(ch->r_io[ATA_BMCMD_PORT].res, - 0x24 + (devno << 3), udmatiming[mode & ATA_MODE_MASK]); - } - else if (mode >= ATA_WDMA0) { - ATA_OUTL(ch->r_io[ATA_BMCMD_PORT].res, - 0x24 + (devno << 3), dmatiming[mode & ATA_MODE_MASK]); - } - else { - ATA_OUTL(ch->r_io[ATA_BMCMD_PORT].res, - 0x20 + (devno << 3), piotiming[mode & ATA_MODE_MASK]); - } + 0x20 + (devno << 3), piotiming[ata_mode2idx(piomode)]); } - atadev->mode = mode; - } + return (mode); } ATA_DECLARE_DRIVER(ata_cyrix); diff --git a/sys/dev/ata/chipsets/ata-highpoint.c b/sys/dev/ata/chipsets/ata-highpoint.c index 101b054f483d..511366a78e1b 100644 --- a/sys/dev/ata/chipsets/ata-highpoint.c +++ b/sys/dev/ata/chipsets/ata-highpoint.c @@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$"); /* local prototypes */ static int ata_highpoint_chipinit(device_t dev); static int ata_highpoint_ch_attach(device_t dev); -static void ata_highpoint_setmode(device_t dev, int mode); +static int ata_highpoint_setmode(device_t dev, int target, int mode); static int ata_highpoint_check_80pin(device_t dev, int mode); /* misc defines */ @@ -143,26 +143,27 @@ ata_highpoint_chipinit(device_t dev) static int ata_highpoint_ch_attach(device_t dev) { - struct ata_channel *ch = device_get_softc(dev); + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); - /* setup the usual register normal pci style */ - if (ata_pci_ch_attach(dev)) - return ENXIO; - - ch->flags |= ATA_ALWAYS_DMASTAT; - return 0; + /* setup the usual register normal pci style */ + if (ata_pci_ch_attach(dev)) + return (ENXIO); + ch->flags |= ATA_ALWAYS_DMASTAT; + ch->flags |= ATA_CHECKS_CABLE; + if (ctlr->chip->cfg1 == HPT_366) + ch->flags |= ATA_NO_ATAPI_DMA; + return (0); } -static void -ata_highpoint_setmode(device_t dev, int mode) +static int +ata_highpoint_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; - u_int32_t timings33[][4] = { + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; + u_int32_t timings33[][4] = { /* HPT366 HPT370 HPT372 HPT374 mode */ { 0x40d0a7aa, 0x06914e57, 0x0d029d5e, 0x0ac1f48a }, /* PIO 0 */ { 0x40d0a7a3, 0x06914e43, 0x0d029d26, 0x0ac1f465 }, /* PIO 1 */ @@ -179,51 +180,41 @@ ata_highpoint_setmode(device_t dev, int mode) { 0x10c9a731, 0x16454e31, 0x1c8a9c62, 0x12ac8242 }, /* UDMA 4 */ { 0, 0x16454e31, 0x1c8a9c62, 0x12848242 }, /* UDMA 5 */ { 0, 0, 0x1c869c62, 0x12808242 } /* UDMA 6 */ - }; + }; - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - if (ctlr->chip->cfg1 == HPT_366 && ata_atapi(dev)) - mode = ata_limit_mode(dev, mode, ATA_PIO_MAX); - - mode = ata_highpoint_check_80pin(dev, mode); - - /* - * most if not all HPT chips cant really handle that the device is - * running at ATA_UDMA6/ATA133 speed, so we cheat at set the device to - * a max of ATA_UDMA5/ATA100 to guard against suboptimal performance - */ - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, - ata_limit_mode(dev, mode, ATA_UDMA5)); - if (bootverbose) - device_printf(dev, "%ssetting %s on HighPoint chip\n", - (error) ? "FAILURE " : "", ata_mode2str(mode)); - if (!error) - pci_write_config(gparent, 0x40 + (devno << 2), + mode = min(mode, ctlr->chip->max_dma); + mode = ata_highpoint_check_80pin(dev, mode); + /* + * most if not all HPT chips cant really handle that the device is + * running at ATA_UDMA6/ATA133 speed, so we cheat at set the device to + * a max of ATA_UDMA5/ATA100 to guard against suboptimal performance + */ + mode = min(mode, ATA_UDMA5); + pci_write_config(parent, 0x40 + (devno << 2), timings33[ata_mode2idx(mode)][ctlr->chip->cfg1], 4); - atadev->mode = mode; + return (mode); } static int ata_highpoint_check_80pin(device_t dev, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); u_int8_t reg, val, res; - if (ctlr->chip->cfg1 == HPT_374 && pci_get_function(gparent) == 1) { + if (ctlr->chip->cfg1 == HPT_374 && pci_get_function(parent) == 1) { reg = ch->unit ? 0x57 : 0x53; - val = pci_read_config(gparent, reg, 1); - pci_write_config(gparent, reg, val | 0x80, 1); + val = pci_read_config(parent, reg, 1); + pci_write_config(parent, reg, val | 0x80, 1); } else { reg = 0x5b; - val = pci_read_config(gparent, reg, 1); - pci_write_config(gparent, reg, val & 0xfe, 1); + val = pci_read_config(parent, reg, 1); + pci_write_config(parent, reg, val & 0xfe, 1); } - res = pci_read_config(gparent, 0x5a, 1) & (ch->unit ? 0x1:0x2); - pci_write_config(gparent, reg, val, 1); + res = pci_read_config(parent, 0x5a, 1) & (ch->unit ? 0x1:0x2); + pci_write_config(parent, reg, val, 1); if (mode > ATA_UDMA2 && res) { ata_print_cable(dev, "controller"); diff --git a/sys/dev/ata/chipsets/ata-intel.c b/sys/dev/ata/chipsets/ata-intel.c index add18d2d2a5f..95e40c1e3fc0 100644 --- a/sys/dev/ata/chipsets/ata-intel.c +++ b/sys/dev/ata/chipsets/ata-intel.c @@ -55,9 +55,9 @@ __FBSDID("$FreeBSD$"); static int ata_intel_chipinit(device_t dev); static int ata_intel_ch_attach(device_t dev); static void ata_intel_reset(device_t dev); -static void ata_intel_old_setmode(device_t dev, int mode); -static void ata_intel_new_setmode(device_t dev, int mode); -static void ata_intel_sata_setmode(device_t dev, int mode); +static int ata_intel_old_setmode(device_t dev, int target, int mode); +static int ata_intel_new_setmode(device_t dev, int target, int mode); +static int ata_intel_sata_getrev(device_t dev, int target); static int ata_intel_31244_ch_attach(device_t dev); static int ata_intel_31244_ch_detach(device_t dev); static int ata_intel_31244_status(device_t dev); @@ -181,6 +181,7 @@ ata_intel_chipinit(device_t dev) ctlr->reset = ata_intel_31244_reset; } ctlr->setmode = ata_sata_setmode; + ctlr->getrev = ata_sata_getrev; } /* non SATA intel chips goes here */ @@ -214,9 +215,8 @@ ata_intel_chipinit(device_t dev) ctlr->r_rid2 = PCIR_BAR(5); if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, &ctlr->r_rid2, RF_ACTIVE))) - ctlr->setmode = ata_intel_sata_setmode; - else - ctlr->setmode = ata_sata_setmode; + ctlr->getrev = ata_intel_sata_getrev; + ctlr->setmode = ata_sata_setmode; } return 0; } @@ -240,6 +240,13 @@ ata_intel_ch_attach(device_t dev) } ch->flags |= ATA_ALWAYS_DMASTAT; + if (ctlr->chip->max_dma >= ATA_SA150) { + if (ctlr->chip->cfg1 == 0 && + (pci_read_config(device_get_parent(dev), 0x90, 1) & 0x04) == 0) + ch->flags |= ATA_NO_SLAVE; + ch->flags |= ATA_SATA; + } else + ch->flags |= ATA_CHECKS_CABLE; return 0; } @@ -259,11 +266,8 @@ ata_intel_reset(device_t dev) /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */ if (pci_read_config(parent, 0x90, 1) & 0x04) mask = 0x0003; - else { + else mask = (0x0001 << ch->unit); - /* XXX SOS should be in intel_ch_attach if we grow it */ - ch->flags |= ATA_NO_SLAVE; - } } pci_write_config(parent, 0x92, pci_read_config(parent, 0x92, 2) & ~mask, 2); DELAY(10); @@ -279,80 +283,70 @@ ata_intel_reset(device_t dev) ata_generic_reset(dev); } -static void -ata_intel_old_setmode(device_t dev, int mode) +static int +ata_intel_old_setmode(device_t dev, int target, int mode) { - /* NOT YET */ + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + + mode = min(mode, ctlr->chip->max_dma); + return (mode); } -static void -ata_intel_new_setmode(device_t dev, int mode) +static int +ata_intel_new_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - u_int32_t reg40 = pci_read_config(gparent, 0x40, 4); - u_int8_t reg44 = pci_read_config(gparent, 0x44, 1); - u_int8_t reg48 = pci_read_config(gparent, 0x48, 1); - u_int16_t reg4a = pci_read_config(gparent, 0x4a, 2); - u_int16_t reg54 = pci_read_config(gparent, 0x54, 2); - u_int32_t mask40 = 0, new40 = 0; - u_int8_t mask44 = 0, new44 = 0; - int error; - u_int8_t timings[] = { 0x00, 0x00, 0x10, 0x21, 0x23, 0x00, 0x21, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23 }; + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; + int piomode; + u_int32_t reg40 = pci_read_config(parent, 0x40, 4); + u_int8_t reg44 = pci_read_config(parent, 0x44, 1); + u_int8_t reg48 = pci_read_config(parent, 0x48, 1); + u_int16_t reg4a = pci_read_config(parent, 0x4a, 2); + u_int16_t reg54 = pci_read_config(parent, 0x54, 2); + u_int32_t mask40 = 0, new40 = 0; + u_int8_t mask44 = 0, new44 = 0; + u_int8_t timings[] = { 0x00, 0x00, 0x10, 0x21, 0x23, 0x00, 0x21, 0x23 }; + u_int8_t utimings[] = { 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02 }; - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - if ( mode > ATA_UDMA2 && !(reg54 & (0x10 << devno))) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { - if (mode >= ATA_UDMA0) { - u_int8_t utimings[] = { 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02 }; - - pci_write_config(gparent, 0x48, reg48 | (0x0001 << devno), 2); - pci_write_config(gparent, 0x4a, - (reg4a & ~(0x3 << (devno << 2))) | - (utimings[mode & ATA_MODE_MASK] << (devno<<2)), 2); + mode = min(mode, ctlr->chip->max_dma); + if (mode > ATA_UDMA2 && !(reg54 & (0x10 << devno))) { + ata_print_cable(dev, "controller"); + mode = ATA_UDMA2; } - else { - pci_write_config(gparent, 0x48, reg48 & ~(0x0001 << devno), 2); - pci_write_config(gparent, 0x4a, (reg4a & ~(0x3 << (devno << 2))),2); + /* Enable/disable UDMA and set timings. */ + if (mode >= ATA_UDMA0) { + pci_write_config(parent, 0x48, reg48 | (0x0001 << devno), 2); + pci_write_config(parent, 0x4a, + (reg4a & ~(0x3 << (devno << 2))) | + (utimings[mode & ATA_MODE_MASK] << (devno<<2)), 2); + piomode = ATA_PIO4; + } else { + pci_write_config(parent, 0x48, reg48 & ~(0x0001 << devno), 2); + pci_write_config(parent, 0x4a, (reg4a & ~(0x3 << (devno << 2))),2); + piomode = mode; } reg54 |= 0x0400; - if (mode >= ATA_UDMA3) - reg54 |= (0x1 << devno); - else - reg54 &= ~(0x1 << devno); + /* Set UDMA reference clock (33/66/133MHz). */ + reg54 &= ~(0x1001 << devno); if (mode >= ATA_UDMA5) reg54 |= (0x1000 << devno); - else - reg54 &= ~(0x1000 << devno); - - pci_write_config(gparent, 0x54, reg54, 2); - + else if (mode >= ATA_UDMA3) + reg54 |= (0x1 << devno); + pci_write_config(parent, 0x54, reg54, 2); + /* Allow PIO/WDMA timing controls. */ reg40 &= ~0x00ff00ff; reg40 |= 0x40774077; - - if (atadev->unit == ATA_MASTER) { + /* Set PIO/WDMA timings. */ + if (target == 0) { mask40 = 0x3300; - new40 = timings[ata_mode2idx(mode)] << 8; - } - else { + new40 = timings[ata_mode2idx(piomode)] << 8; + } else { mask44 = 0x0f; - new44 = ((timings[ata_mode2idx(mode)] & 0x30) >> 2) | - (timings[ata_mode2idx(mode)] & 0x03); + new44 = ((timings[ata_mode2idx(piomode)] & 0x30) >> 2) | + (timings[ata_mode2idx(piomode)] & 0x03); } if (ch->unit) { mask40 <<= 16; @@ -360,43 +354,21 @@ ata_intel_new_setmode(device_t dev, int mode) mask44 <<= 4; new44 <<= 4; } - pci_write_config(gparent, 0x40, (reg40 & ~mask40) | new40, 4); - pci_write_config(gparent, 0x44, (reg44 & ~mask44) | new44, 1); - - atadev->mode = mode; - } + pci_write_config(parent, 0x40, (reg40 & ~mask40) | new40, 4); + pci_write_config(parent, 0x44, (reg44 & ~mask44) | new44, 1); + return (mode); } -static void -ata_intel_sata_setmode(device_t dev, int mode) +static int +ata_intel_sata_getrev(device_t dev, int target) { - struct ata_device *atadev = device_get_softc(dev); - - if (atadev->param.satacapabilities != 0x0000 && - atadev->param.satacapabilities != 0xffff) { - - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - int devno = (ch->unit << 1) + atadev->unit; - - /* on some drives we need to set the transfer mode */ - ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, - ata_limit_mode(dev, mode, ATA_UDMA6)); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; /* set ATA_SSTATUS register offset */ ATA_IDX_OUTL(ch, ATA_IDX_ADDR, devno * 0x100); - /* query SATA STATUS for the speed */ - if ((ATA_IDX_INL(ch, ATA_IDX_DATA) & ATA_SS_CONWELL_MASK) == - ATA_SS_CONWELL_GEN2) - atadev->mode = ATA_SA300; - else - atadev->mode = ATA_SA150; - } - else { - mode = ata_limit_mode(dev, mode, ATA_UDMA5); - if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) - atadev->mode = mode; - } + return ((ATA_IDX_INL(ch, ATA_IDX_DATA) & 0x0f0) >> 4); } static int @@ -439,6 +411,7 @@ ata_intel_31244_ch_attach(device_t dev) ch->r_io[ATA_BMDTP_PORT].offset = ch_offset + 0x74; ch->flags |= ATA_NO_SLAVE; + ch->flags |= ATA_SATA; ata_pci_hw(dev); ch->hw.status = ata_intel_31244_status; ch->hw.tf_write = ata_intel_31244_tf_write; @@ -471,7 +444,9 @@ static void 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); @@ -487,6 +462,7 @@ ata_intel_31244_tf_write(struct ata_request *request) 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; @@ -508,13 +484,16 @@ ata_intel_31244_tf_write(struct ata_request *request) 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 } } diff --git a/sys/dev/ata/chipsets/ata-ite.c b/sys/dev/ata/chipsets/ata-ite.c index 61879172aeb3..250ca648eb5e 100644 --- a/sys/dev/ata/chipsets/ata-ite.c +++ b/sys/dev/ata/chipsets/ata-ite.c @@ -53,8 +53,9 @@ __FBSDID("$FreeBSD$"); /* local prototypes */ static int ata_ite_chipinit(device_t dev); -static void ata_ite_821x_setmode(device_t dev, int mode); -static void ata_ite_8213_setmode(device_t dev, int mode); +static int ata_ite_ch_attach(device_t dev); +static int ata_ite_821x_setmode(device_t dev, int target, int mode); +static int ata_ite_8213_setmode(device_t dev, int target, int mode); /* @@ -105,143 +106,125 @@ ata_ite_chipinit(device_t dev) ctlr->setmode = ata_ite_821x_setmode; } - + ctlr->ch_attach = ata_ite_ch_attach; return 0; } - -static void -ata_ite_821x_setmode(device_t dev, int mode) + +static int +ata_ite_ch_attach(device_t dev) { - device_t gparent = GRANDPARENT(dev); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; - - /* correct the mode for what the HW supports */ - mode = ata_limit_mode(dev, mode, ATA_UDMA6); - - /* check the CBLID bits for 80 conductor cable detection */ - if (mode > ATA_UDMA2 && (pci_read_config(gparent, 0x40, 2) & - (ch->unit ? (1<<3) : (1<<2)))) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - - /* set the wanted mode on the device */ - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%s setting %s on ITE8212F chip\n", - (error) ? "failed" : "success", ata_mode2str(mode)); - - /* if the device accepted the mode change, setup the HW accordingly */ - if (!error) { - if (mode >= ATA_UDMA0) { - u_int8_t udmatiming[] = - { 0x44, 0x42, 0x31, 0x21, 0x11, 0xa2, 0x91 }; - - /* enable UDMA mode */ - pci_write_config(gparent, 0x50, - pci_read_config(gparent, 0x50, 1) & - ~(1 << (devno + 3)), 1); - - /* set UDMA timing */ - pci_write_config(gparent, - 0x56 + (ch->unit << 2) + atadev->unit, - udmatiming[mode & ATA_MODE_MASK], 1); - } - else { - u_int8_t chtiming[] = - { 0xaa, 0xa3, 0xa1, 0x33, 0x31, 0x88, 0x32, 0x31 }; - - /* disable UDMA mode */ - pci_write_config(gparent, 0x50, - pci_read_config(gparent, 0x50, 1) | - (1 << (devno + 3)), 1); - - /* set active and recover timing (shared between master & slave) */ - if (pci_read_config(gparent, 0x54 + (ch->unit << 2), 1) < - chtiming[ata_mode2idx(mode)]) - pci_write_config(gparent, 0x54 + (ch->unit << 2), - chtiming[ata_mode2idx(mode)], 1); - } - atadev->mode = mode; - } + struct ata_channel *ch = device_get_softc(dev); + int error; + + error = ata_pci_ch_attach(dev); + ch->flags |= ATA_CHECKS_CABLE; + return (error); } -static void -ata_ite_8213_setmode(device_t dev, int mode) +static int +ata_ite_821x_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_device *atadev = device_get_softc(dev); - u_int16_t reg40 = pci_read_config(gparent, 0x40, 2); - u_int8_t reg44 = pci_read_config(gparent, 0x44, 1); - u_int8_t reg48 = pci_read_config(gparent, 0x48, 1); - u_int16_t reg4a = pci_read_config(gparent, 0x4a, 2); - u_int16_t reg54 = pci_read_config(gparent, 0x54, 2); - u_int16_t mask40 = 0, new40 = 0; - u_int8_t mask44 = 0, new44 = 0; - int devno = atadev->unit; - int error; - u_int8_t timings[] = { 0x00, 0x00, 0x10, 0x21, 0x23, 0x10, 0x21, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23 }; + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; + int piomode; + u_int8_t udmatiming[] = + { 0x44, 0x42, 0x31, 0x21, 0x11, 0xa2, 0x91 }; + u_int8_t chtiming[] = + { 0xaa, 0xa3, 0xa1, 0x33, 0x31, 0x88, 0x32, 0x31 }; - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - if (mode > ATA_UDMA2 && !(reg54 & (0x10 << devno))) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { + mode = min(mode, ctlr->chip->max_dma); + /* check the CBLID bits for 80 conductor cable detection */ + if (mode > ATA_UDMA2 && (pci_read_config(parent, 0x40, 2) & + (ch->unit ? (1<<3) : (1<<2)))) { + ata_print_cable(dev, "controller"); + mode = ATA_UDMA2; + } if (mode >= ATA_UDMA0) { - u_int8_t utimings[] = { 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10 }; + /* enable UDMA mode */ + pci_write_config(parent, 0x50, + pci_read_config(parent, 0x50, 1) & + ~(1 << (devno + 3)), 1); + /* set UDMA timing */ + pci_write_config(parent, + 0x56 + (ch->unit << 2) + target, + udmatiming[mode & ATA_MODE_MASK], 1); + piomode = ATA_PIO4; + } else { + /* disable UDMA mode */ + pci_write_config(parent, 0x50, + pci_read_config(parent, 0x50, 1) | + (1 << (devno + 3)), 1); + piomode = mode; + } + /* set active and recover timing (shared between master & slave) */ + if (pci_read_config(parent, 0x54 + (ch->unit << 2), 1) < + chtiming[ata_mode2idx(piomode)]) + pci_write_config(parent, 0x54 + (ch->unit << 2), + chtiming[ata_mode2idx(piomode)], 1); + return (mode); +} - pci_write_config(gparent, 0x48, reg48 | (0x0001 << devno), 2); - pci_write_config(gparent, 0x4a, - (reg4a & ~(0x3 << (devno << 2))) | - (utimings[mode & ATA_MODE_MASK] << (devno<<2)), 2); +static int +ata_ite_8213_setmode(device_t dev, int target, int mode) +{ + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + int piomode; + u_int16_t reg40 = pci_read_config(parent, 0x40, 2); + u_int8_t reg44 = pci_read_config(parent, 0x44, 1); + u_int8_t reg48 = pci_read_config(parent, 0x48, 1); + u_int16_t reg4a = pci_read_config(parent, 0x4a, 2); + u_int16_t reg54 = pci_read_config(parent, 0x54, 2); + u_int16_t mask40 = 0, new40 = 0; + u_int8_t mask44 = 0, new44 = 0; + u_int8_t timings[] = { 0x00, 0x00, 0x10, 0x21, 0x23, 0x00, 0x21, 0x23 }; + u_int8_t utimings[] = { 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02 }; + + mode = min(mode, ctlr->chip->max_dma); + + if (mode > ATA_UDMA2 && !(reg54 & (0x10 << target))) { + ata_print_cable(dev, "controller"); + mode = ATA_UDMA2; } - else { - pci_write_config(gparent, 0x48, reg48 & ~(0x0001 << devno), 2); - pci_write_config(gparent, 0x4a, (reg4a & ~(0x3 << (devno << 2))),2); + /* Enable/disable UDMA and set timings. */ + if (mode >= ATA_UDMA0) { + pci_write_config(parent, 0x48, reg48 | (0x0001 << target), 2); + pci_write_config(parent, 0x4a, + (reg4a & ~(0x3 << (target << 2))) | + (utimings[mode & ATA_MODE_MASK] << (target<<2)), 2); + piomode = ATA_PIO4; + } else { + pci_write_config(parent, 0x48, reg48 & ~(0x0001 << target), 2); + pci_write_config(parent, 0x4a, (reg4a & ~(0x3 << (target << 2))),2); + piomode = mode; } - if (mode >= ATA_UDMA2) - reg54 |= (0x1 << devno); - else - reg54 &= ~(0x1 << devno); + /* Set UDMA reference clock (33/66/133MHz). */ + reg54 &= ~(0x1001 << target); if (mode >= ATA_UDMA5) - reg54 |= (0x1000 << devno); - else - reg54 &= ~(0x1000 << devno); - pci_write_config(gparent, 0x54, reg54, 2); - + reg54 |= (0x1000 << target); + else if (mode >= ATA_UDMA3) + reg54 |= (0x1 << target); + pci_write_config(parent, 0x54, reg54, 2); + /* Allow PIO/WDMA timing controls. */ reg40 &= 0xff00; reg40 |= 0x4033; - if (atadev->unit == ATA_MASTER) { + /* Set PIO/WDMA timings. */ + if (target == 0) { reg40 |= (ata_atapi(dev) ? 0x04 : 0x00); mask40 = 0x3300; - new40 = timings[ata_mode2idx(mode)] << 8; + new40 = timings[ata_mode2idx(piomode)] << 8; } else { reg40 |= (ata_atapi(dev) ? 0x40 : 0x00); mask44 = 0x0f; - new44 = ((timings[ata_mode2idx(mode)] & 0x30) >> 2) | - (timings[ata_mode2idx(mode)] & 0x03); + new44 = ((timings[ata_mode2idx(piomode)] & 0x30) >> 2) | + (timings[ata_mode2idx(piomode)] & 0x03); } - pci_write_config(gparent, 0x40, (reg40 & ~mask40) | new40, 4); - pci_write_config(gparent, 0x44, (reg44 & ~mask44) | new44, 1); - - atadev->mode = mode; - } + pci_write_config(parent, 0x40, (reg40 & ~mask40) | new40, 4); + pci_write_config(parent, 0x44, (reg44 & ~mask44) | new44, 1); + return (mode); } ATA_DECLARE_DRIVER(ata_ite); diff --git a/sys/dev/ata/chipsets/ata-jmicron.c b/sys/dev/ata/chipsets/ata-jmicron.c index 25310705ecf3..13524f1e7c6e 100644 --- a/sys/dev/ata/chipsets/ata-jmicron.c +++ b/sys/dev/ata/chipsets/ata-jmicron.c @@ -53,7 +53,8 @@ __FBSDID("$FreeBSD$"); /* local prototypes */ static int ata_jmicron_chipinit(device_t dev); -static void ata_jmicron_setmode(device_t dev, int mode); +static int ata_jmicron_ch_attach(device_t dev); +static int ata_jmicron_setmode(device_t dev, int target, int mode); /* * JMicron chipset support functions @@ -79,13 +80,8 @@ ata_jmicron_probe(device_t dev) if (!(idx = ata_match_chip(dev, ids))) return ENXIO; - if ((pci_read_config(dev, 0xdf, 1) & 0x40) && - (pci_get_function(dev) == (pci_read_config(dev, 0x40, 1) & 0x02 >> 1))) - sprintf(buffer, "JMicron %s %s controller", - idx->text, ata_mode2str(ATA_UDMA6)); - else - sprintf(buffer, "JMicron %s %s controller", - idx->text, ata_mode2str(idx->max_dma)); + sprintf(buffer, "JMicron %s %s controller", + idx->text, ata_mode2str(idx->max_dma)); device_set_desc_copy(dev, buffer); ctlr->chip = idx; ctlr->chipinit = ata_jmicron_chipinit; @@ -108,7 +104,7 @@ ata_jmicron_chipinit(device_t dev) return 0; /* otherwise we are on the PATA part */ - ctlr->ch_attach = ata_pci_ch_attach; + ctlr->ch_attach = ata_jmicron_ch_attach; ctlr->ch_detach = ata_pci_ch_detach; ctlr->reset = ata_generic_reset; ctlr->setmode = ata_jmicron_setmode; @@ -126,7 +122,7 @@ ata_jmicron_chipinit(device_t dev) bus_generic_attach(dev); } } - ctlr->ch_attach = ata_pci_ch_attach; + ctlr->ch_attach = ata_jmicron_ch_attach; ctlr->ch_detach = ata_pci_ch_detach; ctlr->reset = ata_generic_reset; ctlr->setmode = ata_jmicron_setmode; @@ -135,18 +131,30 @@ ata_jmicron_chipinit(device_t dev) return 0; } -static void -ata_jmicron_setmode(device_t dev, int mode) +static int +ata_jmicron_ch_attach(device_t dev) { - struct ata_device *atadev = device_get_softc(dev); + struct ata_channel *ch = device_get_softc(dev); + int error; + + error = ata_pci_ch_attach(dev); + ch->flags |= ATA_CHECKS_CABLE; + return (error); +} +static int +ata_jmicron_setmode(device_t dev, int target, int mode) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + + mode = min(mode, ctlr->chip->max_dma); /* check for 80pin cable present */ - if (pci_read_config(dev, 0x40, 1) & 0x08) - mode = ata_limit_mode(dev, mode, ATA_UDMA2); - else - mode = ata_limit_mode(dev, mode, ATA_UDMA6); - if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) - atadev->mode = mode; + if (mode > ATA_UDMA2 && pci_read_config(dev, 0x40, 1) & 0x08) { + ata_print_cable(dev, "controller"); + mode = ATA_UDMA2; + } + /* Nothing to do to setup mode, the controller snoop SET_FEATURE cmd. */ + return (mode); } ATA_DECLARE_DRIVER(ata_jmicron); diff --git a/sys/dev/ata/chipsets/ata-marvell.c b/sys/dev/ata/chipsets/ata-marvell.c index bda1a17e7fa3..0d11266aa2b6 100644 --- a/sys/dev/ata/chipsets/ata-marvell.c +++ b/sys/dev/ata/chipsets/ata-marvell.c @@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$"); /* local prototypes */ static int ata_marvell_chipinit(device_t dev); static int ata_marvell_ch_attach(device_t dev); -static void ata_marvell_setmode(device_t dev, int mode); +static int ata_marvell_setmode(device_t dev, int target, int mode); static int ata_marvell_edma_ch_attach(device_t dev); static int ata_marvell_edma_ch_detach(device_t dev); static int ata_marvell_edma_status(device_t dev); @@ -170,20 +170,24 @@ ata_marvell_ch_attach(device_t dev) error = ata_pci_ch_attach(dev); /* dont use 32 bit PIO transfers */ ch->flags |= ATA_USE_16BIT; + ch->flags |= ATA_CHECKS_CABLE; return (error); } -static void -ata_marvell_setmode(device_t dev, int mode) +static int +ata_marvell_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_device *atadev = device_get_softc(dev); + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - mode = ata_check_80pin(dev, mode); - if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) - atadev->mode = mode; + mode = min(mode, ctlr->chip->max_dma); + /* Check for 80pin cable present. */ + if (mode > ATA_UDMA2 && ATA_IDX_INB(ch, ATA_BMDEVSPEC_0) & 0x01) { + ata_print_cable(dev, "controller"); + mode = ATA_UDMA2; + } + /* Nothing to do to setup mode, the controller snoop SET_FEATURE cmd. */ + return (mode); } int @@ -210,6 +214,7 @@ ata_marvell_edma_chipinit(device_t dev) ctlr->ch_detach = ata_marvell_edma_ch_detach; ctlr->reset = ata_marvell_edma_reset; ctlr->setmode = ata_sata_setmode; + ctlr->getrev = ata_sata_getrev; ctlr->channels = ctlr->chip->cfg1; /* clear host controller interrupts */ @@ -281,6 +286,7 @@ ata_marvell_edma_ch_attach(device_t dev) ch->flags |= ATA_NO_SLAVE; ch->flags |= ATA_USE_16BIT; /* XXX SOS needed ? */ + ch->flags |= ATA_SATA; ata_generic_hw(dev); ch->hw.begin_transaction = ata_marvell_edma_begin_transaction; ch->hw.end_transaction = ata_marvell_edma_end_transaction; @@ -601,8 +607,6 @@ ata_marvell_edma_dmainit(device_t dev) /* chip does not reliably do 64K DMA transfers */ if (ctlr->chip->cfg2 == MV_50XX || ctlr->chip->cfg2 == MV_60XX) ch->dma.max_iosize = 64 * DEV_BSIZE; - else - ch->dma.max_iosize = (ATA_DMA_ENTRIES - 1) * PAGE_SIZE; } ATA_DECLARE_DRIVER(ata_marvell); diff --git a/sys/dev/ata/chipsets/ata-micron.c b/sys/dev/ata/chipsets/ata-micron.c index ce7587430406..2b74a3305880 100644 --- a/sys/dev/ata/chipsets/ata-micron.c +++ b/sys/dev/ata/chipsets/ata-micron.c @@ -51,11 +51,6 @@ __FBSDID("$FreeBSD$"); #include #include -/* local prototypes */ -static int ata_micron_chipinit(device_t dev); -static void ata_micron_setmode(device_t dev, int mode); - - /* * Cenatek chipset support functions */ @@ -68,34 +63,10 @@ ata_micron_probe(device_t dev) pci_get_devid(dev) == ATA_MICRON_RZ1001) { device_set_desc(dev, "RZ 100? ATA controller !WARNING! data loss/corruption risk"); - ctlr->chipinit = ata_micron_chipinit; + ctlr->chipinit = ata_generic_chipinit; return (BUS_PROBE_DEFAULT); } - else - return ENXIO; -} - -static int -ata_micron_chipinit(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(dev); - - if (ata_setup_interrupt(dev, ata_generic_intr)) - return ENXIO; - - ctlr->setmode = ata_micron_setmode; - return 0; -} - -static void -ata_micron_setmode(device_t dev, int mode) -{ - struct ata_device *atadev = device_get_softc(dev); - - mode = ata_limit_mode(dev, mode, ATA_UDMA2); - mode = ata_check_80pin(dev, mode); - if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) - atadev->mode = mode; + return (ENXIO); } ATA_DECLARE_DRIVER(ata_micron); diff --git a/sys/dev/ata/chipsets/ata-national.c b/sys/dev/ata/chipsets/ata-national.c index 840360ad2b66..20cafa533a83 100644 --- a/sys/dev/ata/chipsets/ata-national.c +++ b/sys/dev/ata/chipsets/ata-national.c @@ -53,8 +53,8 @@ __FBSDID("$FreeBSD$"); /* local prototypes */ static int ata_national_chipinit(device_t dev); -static void ata_national_setmode(device_t dev, int mode); - +static int ata_national_ch_attach(device_t dev); +static int ata_national_setmode(device_t dev, int target, int mode); /* * National chipset support functions @@ -81,53 +81,55 @@ ata_national_chipinit(device_t dev) if (ata_setup_interrupt(dev, ata_generic_intr)) return ENXIO; + ctlr->ch_attach = ata_national_ch_attach; ctlr->setmode = ata_national_setmode; return 0; } -static void -ata_national_setmode(device_t dev, int mode) +static int +ata_national_ch_attach(device_t dev) { - device_t gparent = GRANDPARENT(dev); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - u_int32_t piotiming[] = - { 0x9172d132, 0x21717121, 0x00803020, 0x20102010, 0x00100010, - 0x00803020, 0x20102010, 0x00100010, - 0x00100010, 0x00100010, 0x00100010 }; - u_int32_t dmatiming[] = { 0x80077771, 0x80012121, 0x80002020 }; - u_int32_t udmatiming[] = { 0x80921250, 0x80911140, 0x80911030 }; - int error; + struct ata_channel *ch = device_get_softc(dev); + int error; + + error = ata_pci_ch_attach(dev); + ch->dma.alignment = 16; + ch->dma.max_iosize = 64 * DEV_BSIZE; + return (error); +} - ch->dma.alignment = 16; - ch->dma.max_iosize = 64 * DEV_BSIZE; +static int +ata_national_setmode(device_t dev, int target, int mode) +{ + device_t parent = device_get_parent(dev); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; + int piomode; + u_int32_t piotiming[] = + { 0x9172d132, 0x21717121, 0x00803020, 0x20102010, 0x00100010, + 0x9172d132, 0x20102010, 0x00100010 }; + u_int32_t dmatiming[] = { 0x80077771, 0x80012121, 0x80002020 }; + u_int32_t udmatiming[] = { 0x80921250, 0x80911140, 0x80911030 }; - mode = ata_limit_mode(dev, mode, ATA_UDMA2); + mode = min(mode, ATA_UDMA2); - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%s setting %s on National chip\n", - (error) ? "failed" : "success", ata_mode2str(mode)); - if (!error) { if (mode >= ATA_UDMA0) { - pci_write_config(gparent, 0x44 + (devno << 3), + pci_write_config(parent, 0x44 + (devno << 3), udmatiming[mode & ATA_MODE_MASK], 4); - } - else if (mode >= ATA_WDMA0) { - pci_write_config(gparent, 0x44 + (devno << 3), + piomode = ATA_PIO4; + } else if (mode >= ATA_WDMA0) { + pci_write_config(parent, 0x44 + (devno << 3), dmatiming[mode & ATA_MODE_MASK], 4); - } - else { - pci_write_config(gparent, 0x44 + (devno << 3), - pci_read_config(gparent, 0x44 + (devno << 3), 4) | + piomode = mode; + } else { + pci_write_config(parent, 0x44 + (devno << 3), + pci_read_config(parent, 0x44 + (devno << 3), 4) | 0x80000000, 4); + piomode = mode; } - pci_write_config(gparent, 0x40 + (devno << 3), - piotiming[ata_mode2idx(mode)], 4); - atadev->mode = mode; - } + pci_write_config(parent, 0x40 + (devno << 3), + piotiming[ata_mode2idx(piomode)], 4); + return (mode); } ATA_DECLARE_DRIVER(ata_national); diff --git a/sys/dev/ata/chipsets/ata-netcell.c b/sys/dev/ata/chipsets/ata-netcell.c index c07df0ea2a57..f6a75451ceae 100644 --- a/sys/dev/ata/chipsets/ata-netcell.c +++ b/sys/dev/ata/chipsets/ata-netcell.c @@ -54,8 +54,6 @@ __FBSDID("$FreeBSD$"); /* local prototypes */ static int ata_netcell_chipinit(device_t dev); static int ata_netcell_ch_attach(device_t dev); -static void ata_netcell_setmode(device_t dev, int mode); - /* * NetCell chipset support functions @@ -82,8 +80,7 @@ ata_netcell_chipinit(device_t dev) return ENXIO; ctlr->ch_attach = ata_netcell_ch_attach; - ctlr->ch_detach = ata_pci_ch_detach; - ctlr->setmode = ata_netcell_setmode; + ctlr->setmode = ata_generic_setmode; return 0; } @@ -98,19 +95,7 @@ ata_netcell_ch_attach(device_t dev) /* the NetCell only supports 16 bit PIO transfers */ ch->flags |= ATA_USE_16BIT; - return 0; } -static void -ata_netcell_setmode(device_t dev, int mode) -{ - struct ata_device *atadev = device_get_softc(dev); - - mode = ata_limit_mode(dev, mode, ATA_UDMA2); - mode = ata_check_80pin(dev, mode); - if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) - atadev->mode = mode; -} - ATA_DECLARE_DRIVER(ata_netcell); diff --git a/sys/dev/ata/chipsets/ata-nvidia.c b/sys/dev/ata/chipsets/ata-nvidia.c index cdff82598762..79064f883a37 100644 --- a/sys/dev/ata/chipsets/ata-nvidia.c +++ b/sys/dev/ata/chipsets/ata-nvidia.c @@ -56,7 +56,7 @@ static int ata_nvidia_chipinit(device_t dev); static int ata_nvidia_ch_attach(device_t dev); static int ata_nvidia_status(device_t dev); static void ata_nvidia_reset(device_t dev); -static void ata_nvidia_setmode(device_t dev, int mode); +static int ata_nvidia_setmode(device_t dev, int target, int mode); /* misc defines */ #define NV4 0x01 @@ -231,6 +231,7 @@ ata_nvidia_chipinit(device_t dev) } } ctlr->setmode = ata_sata_setmode; + ctlr->getrev = ata_sata_getrev; } else { /* disable prefetch, postwrite */ @@ -259,7 +260,7 @@ ata_nvidia_ch_attach(device_t dev) ch->hw.status = ata_nvidia_status; ch->flags |= ATA_NO_SLAVE; - + ch->flags |= ATA_SATA; return 0; } @@ -299,36 +300,29 @@ ata_nvidia_reset(device_t dev) ata_generic_reset(dev); } -static void -ata_nvidia_setmode(device_t dev, int mode) +static int +ata_nvidia_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - u_int8_t timings[] = { 0xa8, 0x65, 0x42, 0x22, 0x20, 0x42, 0x22, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; - int modes[7] = { 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 0xc7 }; - int devno = (ch->unit << 1) + atadev->unit; - int reg = 0x63 - devno; - int error; + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; + int piomode; + u_int8_t timings[] = { 0xa8, 0x65, 0x42, 0x22, 0x20, 0xa8, 0x22, 0x20 }; + int modes[7] = { 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 0xc7 }; + int reg = 0x63 - devno; - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - mode = ata_check_80pin(dev, mode); + mode = min(mode, ctlr->chip->max_dma); - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", ata_mode2str(mode), - ctlr->chip->text); - if (!error) { - pci_write_config(gparent, reg - 0x08, timings[ata_mode2idx(mode)], 1); - if (mode >= ATA_UDMA0) - pci_write_config(gparent, reg, modes[mode & ATA_MODE_MASK], 1); - else - pci_write_config(gparent, reg, 0x8b, 1); - atadev->mode = mode; - } + if (mode >= ATA_UDMA0) { + pci_write_config(parent, reg, modes[mode & ATA_MODE_MASK], 1); + piomode = ATA_PIO4; + } else { + pci_write_config(parent, reg, 0x8b, 1); + piomode = mode; + } + pci_write_config(parent, reg - 0x08, timings[ata_mode2idx(piomode)], 1); + return (mode); } ATA_DECLARE_DRIVER(ata_nvidia); diff --git a/sys/dev/ata/chipsets/ata-promise.c b/sys/dev/ata/chipsets/ata-promise.c index ca3243adb74b..2f79a46ba1e7 100644 --- a/sys/dev/ata/chipsets/ata-promise.c +++ b/sys/dev/ata/chipsets/ata-promise.c @@ -58,7 +58,7 @@ static int ata_promise_status(device_t dev); static int ata_promise_dmastart(struct ata_request *request); static int ata_promise_dmastop(struct ata_request *request); static void ata_promise_dmareset(device_t dev); -static void ata_promise_setmode(device_t dev, int mode); +static int ata_promise_setmode(device_t dev, int target, int mode); static int ata_promise_tx2_ch_attach(device_t dev); static int ata_promise_tx2_status(device_t dev); static int ata_promise_mio_ch_attach(device_t dev); @@ -72,7 +72,7 @@ static int ata_promise_mio_pm_write(device_t dev, int port, int reg, u_int32_t r static u_int32_t ata_promise_mio_softreset(device_t dev, int port); static void ata_promise_mio_dmainit(device_t dev); static void ata_promise_mio_setprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); -static void ata_promise_mio_setmode(device_t dev, int mode); +static int ata_promise_mio_setmode(device_t dev, int target, int mode); static void ata_promise_sx4_intr(void *data); static int ata_promise_sx4_command(struct ata_request *request); static int ata_promise_apkt(u_int8_t *bytep, struct ata_request *request); @@ -369,6 +369,8 @@ ata_promise_ch_attach(device_t dev) } ch->hw.status = ata_promise_status; + ch->flags |= ATA_NO_ATAPI_DMA; + ch->flags |= ATA_CHECKS_CABLE; return 0; } @@ -438,15 +440,13 @@ ata_promise_dmareset(device_t dev) ch->flags &= ~ATA_DMA_ACTIVE; } -static void -ata_promise_setmode(device_t dev, int mode) +static int +ata_promise_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; u_int32_t timings[][2] = { /* PR_OLD PR_NEW mode */ { 0x004ff329, 0x004fff2f }, /* PIO 0 */ @@ -465,18 +465,16 @@ ata_promise_setmode(device_t dev, int mode) { 0, 0x004127f3 } /* UDMA 5 */ }; - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); + mode = min(mode, ctlr->chip->max_dma); switch (ctlr->chip->cfg1) { case PR_OLD: case PR_NEW: - if (mode > ATA_UDMA2 && (pci_read_config(gparent, 0x50, 2) & + if (mode > ATA_UDMA2 && (pci_read_config(parent, 0x50, 2) & (ch->unit ? 1 << 11 : 1 << 10))) { ata_print_cable(dev, "controller"); mode = ATA_UDMA2; } - if (ata_atapi(dev) && mode > ATA_PIO_MAX) - mode = ata_limit_mode(dev, mode, ATA_PIO_MAX); break; case PR_TX: @@ -499,19 +497,10 @@ ata_promise_setmode(device_t dev, int mode) break; } - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { if (ctlr->chip->cfg1 < PR_TX) - pci_write_config(gparent, 0x60 + (devno << 2), + pci_write_config(parent, 0x60 + (devno << 2), timings[ata_mode2idx(mode)][ctlr->chip->cfg1], 4); - atadev->mode = mode; - } - return; + return (mode); } static int @@ -523,6 +512,7 @@ ata_promise_tx2_ch_attach(device_t dev) return ENXIO; ch->hw.status = ata_promise_tx2_status; + ch->flags |= ATA_CHECKS_CABLE; return 0; } @@ -565,8 +555,10 @@ ata_promise_mio_ch_attach(device_t dev) ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; ch->r_io[ATA_SCONTROL].offset = 0x408 + (ch->unit << 8); ch->flags |= ATA_NO_SLAVE; + ch->flags |= ATA_SATA; } ch->flags |= ATA_USE_16BIT; + ch->flags |= ATA_CHECKS_CABLE; ata_generic_hw(dev); if (ctlr->chip->cfg2 & PR_SX4X) { @@ -997,20 +989,20 @@ ata_promise_mio_setprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) args->nsegs = nsegs; } -static void -ata_promise_mio_setmode(device_t dev, int mode) +static int +ata_promise_mio_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); - if ( (ctlr->chip->cfg2 == PR_SATA) || - ((ctlr->chip->cfg2 == PR_CMBO) && (ch->unit < 2)) || - (ctlr->chip->cfg2 == PR_SATA2) || - ((ctlr->chip->cfg2 == PR_CMBO2) && (ch->unit < 2))) - ata_sata_setmode(dev, mode); - else - ata_promise_setmode(dev, mode); + if ( (ctlr->chip->cfg2 == PR_SATA) || + ((ctlr->chip->cfg2 == PR_CMBO) && (ch->unit < 2)) || + (ctlr->chip->cfg2 == PR_SATA2) || + ((ctlr->chip->cfg2 == PR_CMBO2) && (ch->unit < 2))) + mode = ata_sata_setmode(dev, target, mode); + else + mode = ata_promise_setmode(dev, target, mode); + return (mode); } static void diff --git a/sys/dev/ata/chipsets/ata-serverworks.c b/sys/dev/ata/chipsets/ata-serverworks.c index 886282ebb376..b5a3fc2e532f 100644 --- a/sys/dev/ata/chipsets/ata-serverworks.c +++ b/sys/dev/ata/chipsets/ata-serverworks.c @@ -60,7 +60,7 @@ static int ata_serverworks_ch_attach(device_t dev); static int ata_serverworks_ch_detach(device_t dev); static void ata_serverworks_tf_read(struct ata_request *request); static void ata_serverworks_tf_write(struct ata_request *request); -static void ata_serverworks_setmode(device_t dev, int mode); +static int ata_serverworks_setmode(device_t dev, int target, int mode); #ifdef __powerpc__ static int ata_serverworks_status(device_t dev); #endif @@ -147,6 +147,7 @@ ata_serverworks_chipinit(device_t dev) ctlr->ch_attach = ata_serverworks_ch_attach; ctlr->ch_detach = ata_serverworks_ch_detach; ctlr->setmode = ata_sata_setmode; + ctlr->getrev = ata_sata_getrev; return 0; } else if (ctlr->chip->cfg1 == SWKS_33) { @@ -213,6 +214,7 @@ ata_serverworks_ch_attach(device_t dev) ch->r_io[ATA_SCONTROL].offset = ch_offset + 0x48; ch->flags |= ATA_NO_SLAVE; + ch->flags |= ATA_SATA; ata_pci_hw(dev); ch->hw.tf_read = ata_serverworks_tf_read; ch->hw.tf_write = ata_serverworks_tf_write; @@ -287,7 +289,9 @@ 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 (request->flags & ATA_R_48BIT) { ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature); @@ -303,6 +307,7 @@ ata_serverworks_tf_write(struct ata_request *request) 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; @@ -324,74 +329,74 @@ ata_serverworks_tf_write(struct ata_request *request) 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 } } -static void -ata_serverworks_setmode(device_t dev, int mode) +static int +ata_serverworks_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int offset = (devno ^ 0x01) << 3; - int error; - u_int8_t piotimings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20, 0x34, 0x22, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; - u_int8_t dmatimings[] = { 0x77, 0x21, 0x20 }; + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; + int offset = (devno ^ 0x01) << 3; + int piomode; + u_int8_t piotimings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 }; + u_int8_t dmatimings[] = { 0x77, 0x21, 0x20 }; - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - mode = ata_check_80pin(dev, mode); - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { + mode = min(mode, ctlr->chip->max_dma); if (mode >= ATA_UDMA0) { - pci_write_config(gparent, 0x56, - (pci_read_config(gparent, 0x56, 2) & + /* Set UDMA mode, enable UDMA, set WDMA2/PIO4 */ + pci_write_config(parent, 0x56, + (pci_read_config(parent, 0x56, 2) & ~(0xf << (devno << 2))) | ((mode & ATA_MODE_MASK) << (devno << 2)), 2); - pci_write_config(gparent, 0x54, - pci_read_config(gparent, 0x54, 1) | + pci_write_config(parent, 0x54, + pci_read_config(parent, 0x54, 1) | (0x01 << devno), 1); - pci_write_config(gparent, 0x44, - (pci_read_config(gparent, 0x44, 4) & + pci_write_config(parent, 0x44, + (pci_read_config(parent, 0x44, 4) & ~(0xff << offset)) | (dmatimings[2] << offset), 4); - } - else if (mode >= ATA_WDMA0) { - pci_write_config(gparent, 0x54, - pci_read_config(gparent, 0x54, 1) & + piomode = ATA_PIO4; + } else if (mode >= ATA_WDMA0) { + /* Disable UDMA, set WDMA mode and timings, calculate PIO. */ + pci_write_config(parent, 0x54, + pci_read_config(parent, 0x54, 1) & ~(0x01 << devno), 1); - pci_write_config(gparent, 0x44, - (pci_read_config(gparent, 0x44, 4) & + pci_write_config(parent, 0x44, + (pci_read_config(parent, 0x44, 4) & ~(0xff << offset)) | (dmatimings[mode & ATA_MODE_MASK] << offset), 4); - } - else - pci_write_config(gparent, 0x54, - pci_read_config(gparent, 0x54, 1) & + piomode = (mode == ATA_WDMA0) ? ATA_PIO0 : + (mode == ATA_WDMA1) ? ATA_PIO3 : ATA_PIO4; + } else { + /* Disable UDMA, set requested PIO. */ + pci_write_config(parent, 0x54, + pci_read_config(parent, 0x54, 1) & ~(0x01 << devno), 1); - - pci_write_config(gparent, 0x40, - (pci_read_config(gparent, 0x40, 4) & + piomode = mode; + } + /* Set PIO mode and timings, calculated above. */ + pci_write_config(parent, 0x4a, + (pci_read_config(parent, 0x4a, 2) & + ~(0xf << (devno << 2))) | + ((piomode - ATA_PIO0) << (devno<<2)),2); + pci_write_config(parent, 0x40, + (pci_read_config(parent, 0x40, 4) & ~(0xff << offset)) | - (piotimings[ata_mode2idx(mode)] << offset), 4); - atadev->mode = mode; - } + (piotimings[ata_mode2idx(piomode)] << offset), 4); + return (mode); } ATA_DECLARE_DRIVER(ata_serverworks); diff --git a/sys/dev/ata/chipsets/ata-siliconimage.c b/sys/dev/ata/chipsets/ata-siliconimage.c index 34bd92f57c52..066e9280e5d9 100644 --- a/sys/dev/ata/chipsets/ata-siliconimage.c +++ b/sys/dev/ata/chipsets/ata-siliconimage.c @@ -54,12 +54,12 @@ __FBSDID("$FreeBSD$"); /* local prototypes */ static int ata_cmd_ch_attach(device_t dev); static int ata_cmd_status(device_t dev); -static void ata_cmd_setmode(device_t dev, int mode); +static int ata_cmd_setmode(device_t dev, int target, int mode); static int ata_sii_ch_attach(device_t dev); static int ata_sii_ch_detach(device_t dev); static int ata_sii_status(device_t dev); static void ata_sii_reset(device_t dev); -static void ata_sii_setmode(device_t dev, int mode); +static int ata_sii_setmode(device_t dev, int target, int mode); static int ata_siiprb_ch_attach(device_t dev); static int ata_siiprb_ch_detach(device_t dev); static int ata_siiprb_status(device_t dev); @@ -145,6 +145,7 @@ ata_sii_chipinit(device_t dev) ctlr->ch_detach = ata_siiprb_ch_detach; ctlr->reset = ata_siiprb_reset; ctlr->setmode = ata_sata_setmode; + ctlr->getrev = ata_sata_getrev; ctlr->channels = (ctlr->chip->cfg2 == SII_4CH) ? 4 : 2; /* reset controller */ @@ -193,6 +194,7 @@ ata_sii_chipinit(device_t dev) if (ctlr->chip->max_dma >= ATA_SA150) { ctlr->reset = ata_sii_reset; ctlr->setmode = ata_sata_setmode; + ctlr->getrev = ata_sata_getrev; } else ctlr->setmode = ata_sii_setmode; @@ -246,59 +248,37 @@ ata_cmd_status(device_t dev) return 0; } -static void -ata_cmd_setmode(device_t dev, int mode) +static int +ata_cmd_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; - - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - mode = ata_check_80pin(dev, mode); - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; int treg = 0x54 + ((devno < 3) ? (devno << 1) : 7); int ureg = ch->unit ? 0x7b : 0x73; - - if (mode >= ATA_UDMA0) { - int udmatimings[][2] = { { 0x31, 0xc2 }, { 0x21, 0x82 }, + int piomode; + uint8_t piotimings[] = { 0xa9, 0x57, 0x44, 0x32, 0x3f, 0x87, 0x32, 0x3f }; + uint8_t udmatimings[][2] = { { 0x31, 0xc2 }, { 0x21, 0x82 }, { 0x11, 0x42 }, { 0x25, 0x8a }, { 0x15, 0x4a }, { 0x05, 0x0a } }; - u_int8_t umode = pci_read_config(gparent, ureg, 1); + mode = min(mode, ctlr->chip->max_dma); + if (mode >= ATA_UDMA0) { + u_int8_t umode = pci_read_config(parent, ureg, 1); - umode &= ~(atadev->unit == ATA_MASTER ? 0x35 : 0xca); - umode |= udmatimings[mode & ATA_MODE_MASK][atadev->unit]; - pci_write_config(gparent, ureg, umode, 1); + umode &= ~(target == 0 ? 0x35 : 0xca); + umode |= udmatimings[mode & ATA_MODE_MASK][target]; + pci_write_config(parent, ureg, umode, 1); + piomode = ATA_PIO4; + } else { + pci_write_config(parent, ureg, + pci_read_config(parent, ureg, 1) & + ~(target == 0 ? 0x35 : 0xca), 1); + piomode = mode; } - else if (mode >= ATA_WDMA0) { - int dmatimings[] = { 0x87, 0x32, 0x3f }; - - pci_write_config(gparent, treg, dmatimings[mode & ATA_MODE_MASK],1); - pci_write_config(gparent, ureg, - pci_read_config(gparent, ureg, 1) & - ~(atadev->unit == ATA_MASTER ? 0x35 : 0xca), 1); - } - else { - int piotimings[] = { 0xa9, 0x57, 0x44, 0x32, 0x3f }; - pci_write_config(gparent, treg, - piotimings[(mode & ATA_MODE_MASK) - ATA_PIO0], 1); - pci_write_config(gparent, ureg, - pci_read_config(gparent, ureg, 1) & - ~(atadev->unit == ATA_MASTER ? 0x35 : 0xca), 1); - } - atadev->mode = mode; - } + pci_write_config(parent, treg, piotimings[ata_mode2idx(piomode)], 1); + return (mode); } static int @@ -335,12 +315,12 @@ ata_sii_ch_attach(device_t dev) ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; ch->r_io[ATA_SCONTROL].offset = 0x100 + (unit01 << 7) + (unit10 << 8); ch->flags |= ATA_NO_SLAVE; + ch->flags |= ATA_SATA; /* enable PHY state change interrupt */ 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; @@ -349,6 +329,8 @@ ata_sii_ch_attach(device_t dev) ata_pci_hw(dev); ch->hw.status = ata_sii_status; + if (ctlr->chip->cfg2 & SII_SETCLK) + ch->flags |= ATA_CHECKS_CABLE; return 0; } @@ -386,69 +368,53 @@ ata_sii_reset(device_t dev) ata_generic_reset(dev); } -static void -ata_sii_setmode(device_t dev, int mode) +static int +ata_sii_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int rego = (ch->unit << 4) + (atadev->unit << 1); - int mreg = ch->unit ? 0x84 : 0x80; - int mask = 0x03 << (atadev->unit << 2); - int mval = pci_read_config(gparent, mreg, 1) & ~mask; - int error; - - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - - if (ctlr->chip->cfg2 & SII_SETCLK) { - if (mode > ATA_UDMA2 && (pci_read_config(gparent, 0x79, 1) & - (ch->unit ? 0x02 : 0x01))) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - } - else - mode = ata_check_80pin(dev, mode); - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (error) - return; - - if (mode >= ATA_UDMA0) { - u_int8_t udmatimings[] = { 0xf, 0xb, 0x7, 0x5, 0x3, 0x2, 0x1 }; - u_int8_t ureg = 0xac + rego; - - pci_write_config(gparent, mreg, - mval | (0x03 << (atadev->unit << 2)), 1); - pci_write_config(gparent, ureg, - (pci_read_config(gparent, ureg, 1) & ~0x3f) | - udmatimings[mode & ATA_MODE_MASK], 1); - - } - else if (mode >= ATA_WDMA0) { - u_int8_t dreg = 0xa8 + rego; - u_int16_t dmatimings[] = { 0x2208, 0x10c2, 0x10c1 }; - - pci_write_config(gparent, mreg, - mval | (0x02 << (atadev->unit << 2)), 1); - pci_write_config(gparent, dreg, dmatimings[mode & ATA_MODE_MASK], 2); - - } - else { + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int rego = (ch->unit << 4) + (target << 1); + int mreg = ch->unit ? 0x84 : 0x80; + int mask = 0x03 << (target << 2); + int mval = pci_read_config(parent, mreg, 1) & ~mask; + int piomode; u_int8_t preg = 0xa4 + rego; + u_int8_t dreg = 0xa8 + rego; + u_int8_t ureg = 0xac + rego; u_int16_t piotimings[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; + u_int16_t dmatimings[] = { 0x2208, 0x10c2, 0x10c1 }; + u_int8_t udmatimings[] = { 0xf, 0xb, 0x7, 0x5, 0x3, 0x2, 0x1 }; - pci_write_config(gparent, mreg, - mval | (0x01 << (atadev->unit << 2)), 1); - pci_write_config(gparent, preg, piotimings[mode & ATA_MODE_MASK], 2); - } - atadev->mode = mode; + mode = min(mode, ctlr->chip->max_dma); + + if (ctlr->chip->cfg2 & SII_SETCLK) { + if (mode > ATA_UDMA2 && (pci_read_config(parent, 0x79, 1) & + (ch->unit ? 0x02 : 0x01))) { + ata_print_cable(dev, "controller"); + mode = ATA_UDMA2; + } + } + if (mode >= ATA_UDMA0) { + pci_write_config(parent, mreg, + mval | (0x03 << (target << 2)), 1); + pci_write_config(parent, ureg, + (pci_read_config(parent, ureg, 1) & ~0x3f) | + udmatimings[mode & ATA_MODE_MASK], 1); + piomode = ATA_PIO4; + } else if (mode >= ATA_WDMA0) { + pci_write_config(parent, mreg, + mval | (0x02 << (target << 2)), 1); + pci_write_config(parent, dreg, dmatimings[mode & ATA_MODE_MASK], 2); + piomode = (mode == ATA_WDMA0) ? ATA_PIO0 : + (mode == ATA_WDMA1) ? ATA_PIO3 : ATA_PIO4; + } else { + pci_write_config(parent, mreg, + mval | (0x01 << (target << 2)), 1); + piomode = mode; + } + pci_write_config(parent, preg, piotimings[ata_mode2idx(piomode)], 2); + return (mode); } diff --git a/sys/dev/ata/chipsets/ata-sis.c b/sys/dev/ata/chipsets/ata-sis.c index 5c74e56edf20..80225053c4d0 100644 --- a/sys/dev/ata/chipsets/ata-sis.c +++ b/sys/dev/ata/chipsets/ata-sis.c @@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$"); static int ata_sis_chipinit(device_t dev); static int ata_sis_ch_attach(device_t dev); static void ata_sis_reset(device_t dev); -static void ata_sis_setmode(device_t dev, int mode); +static int ata_sis_setmode(device_t dev, int target, int mode); /* misc defines */ #define SIS_33 1 @@ -191,6 +191,7 @@ ata_sis_chipinit(device_t dev) ctlr->reset = ata_sis_reset; } ctlr->setmode = ata_sata_setmode; + ctlr->getrev = ata_sata_getrev; return 0; default: return ENXIO; @@ -217,6 +218,7 @@ ata_sis_ch_attach(device_t dev) ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; ch->r_io[ATA_SCONTROL].offset = 0x08 + offset; ch->flags |= ATA_NO_SLAVE; + ch->flags |= ATA_SATA; /* XXX SOS PHY hotplug handling missing in SiS chip ?? */ /* XXX SOS unknown how to enable PHY state change interrupt */ @@ -230,40 +232,30 @@ ata_sis_reset(device_t dev) ata_generic_reset(dev); } -static void -ata_sis_setmode(device_t dev, int mode) +static int +ata_sis_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int devno = (ch->unit << 1) + atadev->unit; - int error; + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); + mode = min(mode, ctlr->chip->max_dma); - if (ctlr->chip->cfg1 == SIS_133NEW) { - if (mode > ATA_UDMA2 && - pci_read_config(gparent, ch->unit ? 0x52 : 0x50,2) & 0x8000) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - } - else { - if (mode > ATA_UDMA2 && - pci_read_config(gparent, 0x48, 1)&(ch->unit ? 0x20 : 0x10)) { - ata_print_cable(dev, "controller"); - mode = ATA_UDMA2; - } - } + if (ctlr->chip->cfg1 == SIS_133NEW) { + if (mode > ATA_UDMA2 && + pci_read_config(parent, ch->unit ? 0x52 : 0x50,2) & 0x8000) { + ata_print_cable(dev, "controller"); + mode = ATA_UDMA2; + } + } else { + if (mode > ATA_UDMA2 && + pci_read_config(parent, 0x48, 1)&(ch->unit ? 0x20 : 0x10)) { + ata_print_cable(dev, "controller"); + mode = ATA_UDMA2; + } + } - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", - ata_mode2str(mode), ctlr->chip->text); - if (!error) { switch (ctlr->chip->cfg1) { case SIS_133NEW: { u_int32_t timings[] = @@ -272,8 +264,8 @@ ata_sis_setmode(device_t dev, int mode) 0x0509347c, 0x0509325c, 0x0509323c, 0x0509322c, 0x0509321c}; u_int32_t reg; - reg = (pci_read_config(gparent, 0x57, 1)&0x40?0x70:0x40)+(devno<<2); - pci_write_config(gparent, reg, timings[ata_mode2idx(mode)], 4); + reg = (pci_read_config(parent, 0x57, 1)&0x40?0x70:0x40)+(devno<<2); + pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 4); break; } case SIS_133OLD: { @@ -283,7 +275,7 @@ ata_sis_setmode(device_t dev, int mode) u_int16_t reg = 0x40 + (devno << 1); - pci_write_config(gparent, reg, timings[ata_mode2idx(mode)], 2); + pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 2); break; } case SIS_100NEW: { @@ -292,7 +284,7 @@ ata_sis_setmode(device_t dev, int mode) 0x0031, 0x8b31, 0x8731, 0x8531, 0x8431, 0x8231, 0x8131 }; u_int16_t reg = 0x40 + (devno << 1); - pci_write_config(gparent, reg, timings[ata_mode2idx(mode)], 2); + pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 2); break; } case SIS_100OLD: @@ -303,12 +295,11 @@ ata_sis_setmode(device_t dev, int mode) 0x0301, 0xf301, 0xd301, 0xb301, 0xa301, 0x9301, 0x8301 }; u_int16_t reg = 0x40 + (devno << 1); - pci_write_config(gparent, reg, timings[ata_mode2idx(mode)], 2); + pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 2); break; } } - atadev->mode = mode; - } + return (mode); } ATA_DECLARE_DRIVER(ata_sis); diff --git a/sys/dev/ata/chipsets/ata-via.c b/sys/dev/ata/chipsets/ata-via.c index 47ebd0a15d83..9aea45d9a9f1 100644 --- a/sys/dev/ata/chipsets/ata-via.c +++ b/sys/dev/ata/chipsets/ata-via.c @@ -56,9 +56,9 @@ static int ata_via_chipinit(device_t dev); static int ata_via_ch_attach(device_t dev); static int ata_via_ch_detach(device_t dev); static void ata_via_reset(device_t dev); -static void ata_via_old_setmode(device_t dev, int mode); +static int ata_via_old_setmode(device_t dev, int target, int mode); static void ata_via_southbridge_fixup(device_t dev); -static void ata_via_new_setmode(device_t dev, int mode); +static int ata_via_new_setmode(device_t dev, int target, int mode); /* misc defines */ #define VIA33 0 @@ -152,9 +152,9 @@ ata_via_chipinit(device_t dev) if (ctlr->chip->cfg2 & VIABAR) { ctlr->channels = 3; ctlr->setmode = ata_via_new_setmode; - } - else + } else ctlr->setmode = ata_sata_setmode; + ctlr->getrev = ata_sata_getrev; return 0; } @@ -233,6 +233,7 @@ ata_via_ch_attach(device_t dev) ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; ch->r_io[ATA_SCONTROL].offset = 0x08 + (ch->unit << ctlr->chip->cfg1); ch->flags |= ATA_NO_SLAVE; + ch->flags |= ATA_SATA; /* XXX SOS PHY hotplug handling missing in VIA chip ?? */ /* XXX SOS unknown how to enable PHY state change interrupt */ @@ -277,75 +278,63 @@ ata_via_reset(device_t dev) ata_generic_reset(dev); } -static void -ata_via_new_setmode(device_t dev, int mode) +static int +ata_via_new_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - int error; + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); - if ((ctlr->chip->cfg2 & VIABAR) && (ch->unit > 1)) { - u_int8_t pio_timings[] = { 0xa8, 0x65, 0x65, 0x32, 0x20, - 0x65, 0x32, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; - u_int8_t dma_timings[] = { 0xee, 0xe8, 0xe6, 0xe4, 0xe2, 0xe1, 0xe0 }; + if ((ctlr->chip->cfg2 & VIABAR) && (ch->unit > 1)) { + int piomode; + u_int8_t pio_timings[] = { 0xa8, 0x65, 0x65, 0x32, 0x20 }; + u_int8_t dma_timings[] = { 0xee, 0xe8, 0xe6, 0xe4, 0xe2, 0xe1, 0xe0 }; - mode = ata_check_80pin(dev, ata_limit_mode(dev, mode, ATA_UDMA6)); - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", ata_mode2str(mode), - ctlr->chip->text); - if (!error) { - pci_write_config(gparent, 0xab, pio_timings[ata_mode2idx(mode)], 1); - if (mode >= ATA_UDMA0) - pci_write_config(gparent, 0xb3, + /* This chip can't do WDMA. */ + if (mode >= ATA_WDMA0 && mode < ATA_UDMA0) + mode = ATA_PIO4; + if (mode >= ATA_UDMA0) { + pci_write_config(parent, 0xb3, dma_timings[mode & ATA_MODE_MASK], 1); - atadev->mode = mode; - } - } - else - ata_sata_setmode(dev, mode); + piomode = ATA_PIO4; + } else + piomode = mode; + pci_write_config(parent, 0xab, pio_timings[ata_mode2idx(piomode)], 1); + } else + mode = ata_sata_setmode(dev, target, mode); + return (mode); } -static void -ata_via_old_setmode(device_t dev, int mode) +static int +ata_via_old_setmode(device_t dev, int target, int mode) { - device_t gparent = GRANDPARENT(dev); - struct ata_pci_controller *ctlr = device_get_softc(gparent); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - struct ata_device *atadev = device_get_softc(dev); - u_int8_t timings[] = { 0xa8, 0x65, 0x42, 0x22, 0x20, 0x42, 0x22, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; - int modes[][7] = { - { 0xc2, 0xc1, 0xc0, 0x00, 0x00, 0x00, 0x00 }, /* VIA ATA33 */ - { 0xee, 0xec, 0xea, 0xe9, 0xe8, 0x00, 0x00 }, /* VIA ATA66 */ - { 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0, 0x00 }, /* VIA ATA100 */ - { 0xf7, 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0 } }; /* VIA ATA133 */ - int devno = (ch->unit << 1) + atadev->unit; - int reg = 0x53 - devno; - int error; + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int devno = (ch->unit << 1) + target; + int reg = 0x53 - devno; + int piomode; + uint8_t timings[] = { 0xa8, 0x65, 0x42, 0x22, 0x20, 0xa8, 0x22, 0x20 }; + uint8_t modes[][7] = { + { 0xc2, 0xc1, 0xc0, 0x00, 0x00, 0x00, 0x00 }, /* VIA ATA33 */ + { 0xee, 0xec, 0xea, 0xe9, 0xe8, 0x00, 0x00 }, /* VIA ATA66 */ + { 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0, 0x00 }, /* VIA ATA100 */ + { 0xf7, 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0 } }; /* VIA ATA133 */ - mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); - mode = ata_check_80pin(dev, mode); - - error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); - if (bootverbose) - device_printf(dev, "%ssetting %s on %s chip\n", - (error) ? "FAILURE " : "", ata_mode2str(mode), - ctlr->chip->text); - if (!error) { - if (ctlr->chip->cfg1 != VIA133) - pci_write_config(gparent, reg - 0x08,timings[ata_mode2idx(mode)],1); - if (mode >= ATA_UDMA0) - pci_write_config(gparent, reg, + mode = min(mode, ctlr->chip->max_dma); + /* Set UDMA timings */ + if (mode >= ATA_UDMA0) { + pci_write_config(parent, reg, modes[ctlr->chip->cfg1][mode & ATA_MODE_MASK], 1); - else - pci_write_config(gparent, reg, 0x8b, 1); - atadev->mode = mode; - } + piomode = ATA_PIO4; + } else { + pci_write_config(parent, reg, 0x8b, 1); + piomode = mode; + } + /* Set WDMA/PIO timings */ + if (ctlr->chip->cfg1 != VIA133) + pci_write_config(parent, reg - 0x08,timings[ata_mode2idx(piomode)], 1); + return (mode); } static void diff --git a/sys/powerpc/powermac/ata_dbdma.c b/sys/powerpc/powermac/ata_dbdma.c index b08ade6bc076..c8f37581b422 100644 --- a/sys/powerpc/powermac/ata_dbdma.c +++ b/sys/powerpc/powermac/ata_dbdma.c @@ -204,7 +204,6 @@ static int ata_dbdma_load(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_dbdma_dmaload_args args; int error; @@ -230,7 +229,7 @@ ata_dbdma_load(struct ata_request *request, void *addr, int *entries) return EIO; } - request->dma = &ch->dma.slot[atadev->unit]; + request->dma = &ch->dma.slot[0]; if ((error = bus_dmamap_load(request->dma->data_tag, request->dma->data_map, request->data, request->bytecount, diff --git a/sys/powerpc/powermac/ata_kauai.c b/sys/powerpc/powermac/ata_kauai.c index 415d0fb0e69e..f7b6daa5a7b9 100644 --- a/sys/powerpc/powermac/ata_kauai.c +++ b/sys/powerpc/powermac/ata_kauai.c @@ -85,7 +85,7 @@ __FBSDID("$FreeBSD$"); */ static int ata_kauai_probe(device_t dev); static int ata_kauai_attach(device_t dev); -static void ata_kauai_setmode(device_t parent, device_t dev); +static int ata_kauai_setmode(device_t dev, int target, int mode); static int ata_kauai_begin_transaction(struct ata_request *request); static device_method_t ata_kauai_methods[] = { @@ -307,34 +307,26 @@ ata_kauai_attach(device_t dev) return ata_attach(dev); } -static void -ata_kauai_setmode(device_t parent, device_t dev) +static int +ata_kauai_setmode(device_t dev, int target, int mode) { - struct ata_device *atadev = device_get_softc(dev); - struct ata_kauai_softc *sc = device_get_softc(parent); - uint32_t mode; + struct ata_kauai_softc *sc = device_get_softc(dev); - mode = ata_limit_mode(dev,atadev->mode, - (sc->shasta) ? ATA_UDMA6 : ATA_UDMA5); - - if (ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) - return; - - atadev->mode = mode; + mode = min(mode,sc->shasta ? ATA_UDMA6 : ATA_UDMA5); if (sc->shasta) { switch (mode & ATA_DMA_MASK) { case ATA_UDMA0: - sc->udmaconf[atadev->unit] + sc->udmaconf[target] = udma_timing_shasta[mode & ATA_MODE_MASK]; break; case ATA_WDMA0: - sc->udmaconf[atadev->unit] = 0; - sc->wdmaconf[atadev->unit] + sc->udmaconf[target] = 0; + sc->wdmaconf[target] = dma_timing_shasta[mode & ATA_MODE_MASK]; break; default: - sc->pioconf[atadev->unit] + sc->pioconf[target] = pio_timing_shasta[(mode & ATA_MODE_MASK) - ATA_PIO0]; break; @@ -342,32 +334,33 @@ ata_kauai_setmode(device_t parent, device_t dev) } else { switch (mode & ATA_DMA_MASK) { case ATA_UDMA0: - sc->udmaconf[atadev->unit] + sc->udmaconf[target] = udma_timing_kauai[mode & ATA_MODE_MASK]; break; case ATA_WDMA0: - sc->udmaconf[atadev->unit] = 0; - sc->wdmaconf[atadev->unit] + sc->udmaconf[target] = 0; + sc->wdmaconf[target] = dma_timing_kauai[mode & ATA_MODE_MASK]; break; default: - sc->pioconf[atadev->unit] + sc->pioconf[target] = pio_timing_kauai[(mode & ATA_MODE_MASK) - ATA_PIO0]; break; } } + + return (mode); } static int ata_kauai_begin_transaction(struct ata_request *request) { - struct ata_device *atadev = device_get_softc(request->dev); struct ata_kauai_softc *sc = device_get_softc(request->parent); - bus_write_4(sc->sc_memr, UDMA_CONFIG_REG, sc->udmaconf[atadev->unit]); + bus_write_4(sc->sc_memr, UDMA_CONFIG_REG, sc->udmaconf[request->unit]); bus_write_4(sc->sc_memr, PIO_CONFIG_REG, - sc->wdmaconf[atadev->unit] | sc->pioconf[atadev->unit]); + sc->wdmaconf[request->unit] | sc->pioconf[request->unit]); return ata_begin_transaction(request); } diff --git a/sys/powerpc/powermac/ata_macio.c b/sys/powerpc/powermac/ata_macio.c index 320e86e33819..447009da7ea0 100644 --- a/sys/powerpc/powermac/ata_macio.c +++ b/sys/powerpc/powermac/ata_macio.c @@ -111,7 +111,7 @@ static const struct ide_timings udma_timings[5] = { * Define the macio ata bus attachment. */ static int ata_macio_probe(device_t dev); -static void ata_macio_setmode(device_t parent, device_t dev); +static int ata_macio_setmode(device_t dev, int target, int mode); static int ata_macio_attach(device_t dev); static int ata_macio_begin_transaction(struct ata_request *request); @@ -193,7 +193,7 @@ ata_macio_probe(device_t dev) ata_default_registers(dev); ch->unit = 0; - ch->flags |= ATA_USE_16BIT; + ch->flags |= ATA_USE_16BIT | ATA_NO_ATAPI_DMA; ata_generic_hw(dev); return (ata_probe(dev)); @@ -247,26 +247,15 @@ ata_macio_attach(device_t dev) return ata_attach(dev); } -static void -ata_macio_setmode(device_t parent, device_t dev) +static int +ata_macio_setmode(device_t dev, int target, int mode) { - struct ata_device *atadev = device_get_softc(dev); - struct ata_macio_softc *sc = device_get_softc(parent); - int mode = atadev->mode; + struct ata_macio_softc *sc = device_get_softc(dev); int min_cycle = 0, min_active = 0; int cycle_tick = 0, act_tick = 0, inact_tick = 0, half_tick; - mode = ata_limit_mode(dev, mode, sc->max_mode); - - /* XXX Some controllers don't work correctly with ATAPI DMA */ - if (atadev->param.config & ATA_PROTO_ATAPI) - mode = ata_limit_mode(dev, mode, ATA_PIO_MAX); - - if (ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) - return; - - atadev->mode = mode; + mode = min(mode, sc->max_mode); if ((mode & ATA_DMA_MASK) == ATA_UDMA0) { min_cycle = udma_timings[mode & ATA_MODE_MASK].cycle; @@ -276,7 +265,7 @@ ata_macio_setmode(device_t parent, device_t dev) act_tick = ATA_TIME_TO_TICK(sc->rev,min_active); /* mask: 0x1ff00000 */ - sc->udmaconf[atadev->unit] = + sc->udmaconf[target] = (cycle_tick << 21) | (act_tick << 25) | 0x100000; } else if ((mode & ATA_DMA_MASK) == ATA_WDMA0) { min_cycle = dma_timings[mode & ATA_MODE_MASK].cycle; @@ -288,7 +277,7 @@ ata_macio_setmode(device_t parent, device_t dev) if (sc->rev == 4) { inact_tick = cycle_tick - act_tick; /* mask: 0x001ffc00 */ - sc->wdmaconf[atadev->unit] = + sc->wdmaconf[target] = (act_tick << 10) | (inact_tick << 15); } else { inact_tick = cycle_tick - act_tick - DMA_REC_OFFSET; @@ -297,7 +286,7 @@ ata_macio_setmode(device_t parent, device_t dev) half_tick = 0; /* XXX */ /* mask: 0xfffff800 */ - sc->wdmaconf[atadev->unit] = (half_tick << 21) + sc->wdmaconf[target] = (half_tick << 21) | (inact_tick << 16) | (act_tick << 11); } } else { @@ -313,7 +302,7 @@ ata_macio_setmode(device_t parent, device_t dev) inact_tick = cycle_tick - act_tick; /* mask: 0x000003ff */ - sc->pioconf[atadev->unit] = + sc->pioconf[target] = (inact_tick << 5) | act_tick; } else { if (act_tick < PIO_ACT_MIN) @@ -324,21 +313,22 @@ ata_macio_setmode(device_t parent, device_t dev) inact_tick = PIO_REC_MIN; /* mask: 0x000007ff */ - sc->pioconf[atadev->unit] = + sc->pioconf[target] = (inact_tick << 5) | act_tick; } } + + return (mode); } static int ata_macio_begin_transaction(struct ata_request *request) { - struct ata_device *atadev = device_get_softc(request->dev); struct ata_macio_softc *sc = device_get_softc(request->parent); bus_write_4(sc->sc_mem, ATA_MACIO_TIMINGREG, - sc->udmaconf[atadev->unit] | sc->wdmaconf[atadev->unit] - | sc->pioconf[atadev->unit]); + sc->udmaconf[request->unit] | sc->wdmaconf[request->unit] + | sc->pioconf[request->unit]); return ata_begin_transaction(request); } diff --git a/sys/powerpc/psim/ata_iobus.c b/sys/powerpc/psim/ata_iobus.c index a70d0087a87a..60f6c5088709 100644 --- a/sys/powerpc/psim/ata_iobus.c +++ b/sys/powerpc/psim/ata_iobus.c @@ -210,7 +210,7 @@ ata_iobus_release_resource(device_t dev, device_t child, int type, int rid, */ static int ata_iobus_sub_probe(device_t dev); -static void ata_iobus_sub_setmode(device_t parent, device_t dev); +static int ata_iobus_sub_setmode(device_t dev, int target, int mode); static device_method_t ata_iobus_sub_methods[] = { /* Device interface */ @@ -245,11 +245,9 @@ ata_iobus_sub_probe(device_t dev) return ata_probe(dev); } -static void -ata_iobus_sub_setmode(device_t parent, device_t dev) +static int +ata_iobus_sub_setmode(device_t parent, int target, int mode) { - struct ata_device *atadev = device_get_softc(dev); - /* Only ever PIO mode here... */ - atadev->mode = ATA_PIO; + return (ATA_PIO); }