Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ahci/ahci.c
Show First 20 Lines • Show All 1,118 Lines • ▼ Show 20 Lines | if (error != 0 || (error = dcba.error) != 0) { | ||||
bus_dmamem_free(ch->dma.rfis_tag, ch->dma.rfis, ch->dma.rfis_map); | bus_dmamem_free(ch->dma.rfis_tag, ch->dma.rfis, ch->dma.rfis_map); | ||||
goto error; | goto error; | ||||
} | } | ||||
ch->dma.rfis_bus = dcba.maddr; | ch->dma.rfis_bus = dcba.maddr; | ||||
/* Data area. */ | /* Data area. */ | ||||
error = bus_dma_tag_create(bus_get_dma_tag(dev), 2, 0, | error = bus_dma_tag_create(bus_get_dma_tag(dev), 2, 0, | ||||
BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, | BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, | ||||
NULL, NULL, | NULL, NULL, | ||||
AHCI_SG_ENTRIES * PAGE_SIZE * ch->numslots, | AHCI_SG_ENTRIES * PAGE_SIZE, AHCI_SG_ENTRIES, AHCI_PRD_MAX, | ||||
AHCI_SG_ENTRIES, AHCI_PRD_MAX, | |||||
0, busdma_lock_mutex, &ch->mtx, &ch->dma.data_tag); | 0, busdma_lock_mutex, &ch->mtx, &ch->dma.data_tag); | ||||
if (error != 0) | if (error != 0) | ||||
goto error; | goto error; | ||||
return; | return; | ||||
error: | error: | ||||
device_printf(dev, "WARNING - DMA initialization failed, error %d\n", | device_printf(dev, "WARNING - DMA initialization failed, error %d\n", | ||||
error); | error); | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | ahci_slotsalloc(device_t dev) | ||||
/* Alloc and setup command/dma slots */ | /* Alloc and setup command/dma slots */ | ||||
bzero(ch->slot, sizeof(ch->slot)); | bzero(ch->slot, sizeof(ch->slot)); | ||||
for (i = 0; i < ch->numslots; i++) { | for (i = 0; i < ch->numslots; i++) { | ||||
struct ahci_slot *slot = &ch->slot[i]; | struct ahci_slot *slot = &ch->slot[i]; | ||||
slot->ch = ch; | slot->ch = ch; | ||||
slot->slot = i; | slot->slot = i; | ||||
slot->state = AHCI_SLOT_EMPTY; | slot->state = AHCI_SLOT_EMPTY; | ||||
slot->ct_offset = AHCI_CT_OFFSET + AHCI_CT_SIZE * i; | |||||
slot->ccb = NULL; | slot->ccb = NULL; | ||||
callout_init_mtx(&slot->timeout, &ch->mtx, 0); | callout_init_mtx(&slot->timeout, &ch->mtx, 0); | ||||
if (bus_dmamap_create(ch->dma.data_tag, 0, &slot->dma.data_map)) | if (bus_dmamap_create(ch->dma.data_tag, 0, &slot->dma.data_map)) | ||||
device_printf(ch->dev, "FAILURE - create data_map\n"); | device_printf(ch->dev, "FAILURE - create data_map\n"); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 439 Lines • ▼ Show 20 Lines | ahci_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error) | ||||
if (error) { | if (error) { | ||||
device_printf(ch->dev, "DMA load error\n"); | device_printf(ch->dev, "DMA load error\n"); | ||||
ahci_end_transaction(slot, AHCI_ERR_INVALID); | ahci_end_transaction(slot, AHCI_ERR_INVALID); | ||||
return; | return; | ||||
} | } | ||||
KASSERT(nsegs <= AHCI_SG_ENTRIES, ("too many DMA segment entries\n")); | KASSERT(nsegs <= AHCI_SG_ENTRIES, ("too many DMA segment entries\n")); | ||||
/* Get a piece of the workspace for this request */ | /* Get a piece of the workspace for this request */ | ||||
ctp = (struct ahci_cmd_tab *) | ctp = (struct ahci_cmd_tab *)(ch->dma.work + slot->ct_offset); | ||||
(ch->dma.work + AHCI_CT_OFFSET + (AHCI_CT_SIZE * slot->slot)); | |||||
/* Fill S/G table */ | /* Fill S/G table */ | ||||
prd = &ctp->prd_tab[0]; | prd = &ctp->prd_tab[0]; | ||||
for (i = 0; i < nsegs; i++) { | for (i = 0; i < nsegs; i++) { | ||||
prd[i].dba = htole64(segs[i].ds_addr); | prd[i].dba = htole64(segs[i].ds_addr); | ||||
prd[i].dbc = htole32((segs[i].ds_len - 1) & AHCI_PRD_MASK); | prd[i].dbc = htole32((segs[i].ds_len - 1) & AHCI_PRD_MASK); | ||||
} | } | ||||
slot->dma.nsegs = nsegs; | slot->dma.nsegs = nsegs; | ||||
bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map, | bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map, | ||||
Show All 12 Lines | ahci_execute_transaction(struct ahci_slot *slot) | ||||
union ccb *ccb = slot->ccb; | union ccb *ccb = slot->ccb; | ||||
int port = ccb->ccb_h.target_id & 0x0f; | int port = ccb->ccb_h.target_id & 0x0f; | ||||
int fis_size, i, softreset; | int fis_size, i, softreset; | ||||
uint8_t *fis = ch->dma.rfis + 0x40; | uint8_t *fis = ch->dma.rfis + 0x40; | ||||
uint8_t val; | uint8_t val; | ||||
uint16_t cmd_flags; | uint16_t cmd_flags; | ||||
/* Get a piece of the workspace for this request */ | /* Get a piece of the workspace for this request */ | ||||
ctp = (struct ahci_cmd_tab *) | ctp = (struct ahci_cmd_tab *)(ch->dma.work + slot->ct_offset); | ||||
(ch->dma.work + AHCI_CT_OFFSET + (AHCI_CT_SIZE * slot->slot)); | |||||
/* Setup the FIS for this request */ | /* Setup the FIS for this request */ | ||||
if (!(fis_size = ahci_setup_fis(ch, ctp, ccb, slot->slot))) { | if (!(fis_size = ahci_setup_fis(ch, ctp, ccb, slot->slot))) { | ||||
device_printf(ch->dev, "Setting up SATA FIS failed\n"); | device_printf(ch->dev, "Setting up SATA FIS failed\n"); | ||||
ahci_end_transaction(slot, AHCI_ERR_INVALID); | ahci_end_transaction(slot, AHCI_ERR_INVALID); | ||||
return; | return; | ||||
} | } | ||||
/* Setup the command list entry */ | /* Setup the command list entry */ | ||||
clp = (struct ahci_cmd_list *) | clp = (struct ahci_cmd_list *) | ||||
Show All 20 Lines | if (ccb->ataio.cmd.control & ATA_A_RESET) { | ||||
/* Prepare FIS receive area for check. */ | /* Prepare FIS receive area for check. */ | ||||
for (i = 0; i < 20; i++) | for (i = 0; i < 20; i++) | ||||
fis[i] = 0xff; | fis[i] = 0xff; | ||||
} | } | ||||
} else | } else | ||||
softreset = 0; | softreset = 0; | ||||
clp->bytecount = 0; | clp->bytecount = 0; | ||||
clp->cmd_flags = htole16(cmd_flags); | clp->cmd_flags = htole16(cmd_flags); | ||||
clp->cmd_table_phys = htole64(ch->dma.work_bus + AHCI_CT_OFFSET + | clp->cmd_table_phys = htole64(ch->dma.work_bus + slot->ct_offset); | ||||
(AHCI_CT_SIZE * slot->slot)); | |||||
bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, | bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, | ||||
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | ||||
bus_dmamap_sync(ch->dma.rfis_tag, ch->dma.rfis_map, | bus_dmamap_sync(ch->dma.rfis_tag, ch->dma.rfis_map, | ||||
BUS_DMASYNC_PREREAD); | BUS_DMASYNC_PREREAD); | ||||
/* Set ACTIVE bit for NCQ commands. */ | /* Set ACTIVE bit for NCQ commands. */ | ||||
if ((ccb->ccb_h.func_code == XPT_ATA_IO) && | if ((ccb->ccb_h.func_code == XPT_ATA_IO) && | ||||
(ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) { | (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) { | ||||
ATA_OUTL(ch->r_mem, AHCI_P_SACT, 1 << slot->slot); | ATA_OUTL(ch->r_mem, AHCI_P_SACT, 1 << slot->slot); | ||||
▲ Show 20 Lines • Show All 1,140 Lines • ▼ Show 20 Lines | case XPT_PATH_INQ: /* Path routing inquiry */ | ||||
strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); | strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); | ||||
strlcpy(cpi->hba_vid, "AHCI", HBA_IDLEN); | strlcpy(cpi->hba_vid, "AHCI", HBA_IDLEN); | ||||
strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); | strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); | ||||
cpi->unit_number = cam_sim_unit(sim); | cpi->unit_number = cam_sim_unit(sim); | ||||
cpi->transport = XPORT_SATA; | cpi->transport = XPORT_SATA; | ||||
cpi->transport_version = XPORT_VERSION_UNSPECIFIED; | cpi->transport_version = XPORT_VERSION_UNSPECIFIED; | ||||
cpi->protocol = PROTO_ATA; | cpi->protocol = PROTO_ATA; | ||||
cpi->protocol_version = PROTO_VERSION_UNSPECIFIED; | cpi->protocol_version = PROTO_VERSION_UNSPECIFIED; | ||||
cpi->maxio = MAXPHYS; | cpi->maxio = ctob(AHCI_SG_ENTRIES - 1); | ||||
/* ATI SB600 can't handle 256 sectors with FPDMA (NCQ). */ | /* ATI SB600 can't handle 256 sectors with FPDMA (NCQ). */ | ||||
if (ch->quirks & AHCI_Q_MAXIO_64K) | if (ch->quirks & AHCI_Q_MAXIO_64K) | ||||
cpi->maxio = min(cpi->maxio, 128 * 512); | cpi->maxio = min(cpi->maxio, 128 * 512); | ||||
cpi->hba_vendor = ch->vendorid; | cpi->hba_vendor = ch->vendorid; | ||||
cpi->hba_device = ch->deviceid; | cpi->hba_device = ch->deviceid; | ||||
cpi->hba_subvendor = ch->subvendorid; | cpi->hba_subvendor = ch->subvendorid; | ||||
cpi->hba_subdevice = ch->subdeviceid; | cpi->hba_subdevice = ch->subdeviceid; | ||||
cpi->ccb_h.status = CAM_REQ_CMP; | cpi->ccb_h.status = CAM_REQ_CMP; | ||||
Show All 30 Lines |