/* **************************************************************** * Inicializa o DMA para os Controladores PATA * **************************************************************** */ void ata_stub_pata_setmode (PCIDATA *pci, ATA_DEVICE *adp, int mode) { #if (0) /*******************************************************/ ATA_PCI_CTLR *ctlrp = pci->pci_dev_info_ptr; const ATA_CHIP_ID *idp = ctlrp->ac_idp; #endif /*******************************************************/ if (ata_command (adp, ATA_C_SETFEATURES, 0, mode, ATA_C_F_SETXFER, 0)) return; adp->ad_transfer_mode = mode; } /* end ata_stub_new_setmode */
static int ata_getparam(struct ata_device *atadev, u_int8_t command) { struct ata_params *ata_parm; int retry = 0; if (!(ata_parm = malloc(sizeof(struct ata_params), M_ATA, M_NOWAIT))) { ata_prtdev(atadev, "malloc for identify data failed\n"); return -1; } /* apparently some devices needs this repeated */ do { if (ata_command(atadev, command, 0, 0, 0, ATA_IMMEDIATE)) { ata_prtdev(atadev, "%s identify failed\n", command == ATA_C_ATAPI_IDENTIFY ? "ATAPI" : "ATA"); free(ata_parm, M_ATA); return -1; } if (retry++ > 4) { ata_prtdev(atadev, "%s identify retries exceeded\n", command == ATA_C_ATAPI_IDENTIFY ? "ATAPI" : "ATA"); free(ata_parm, M_ATA); return -1; } } while (ata_wait(atadev, ((command == ATA_C_ATAPI_IDENTIFY) ? ATA_S_DRQ : (ATA_S_READY|ATA_S_DSC|ATA_S_DRQ)))); ATA_INSW(atadev->channel->r_io, ATA_DATA, (int16_t *)ata_parm, sizeof(struct ata_params)/sizeof(int16_t)); if (command == ATA_C_ATA_IDENTIFY || !((ata_parm->model[0] == 'N' && ata_parm->model[1] == 'E') || (ata_parm->model[0] == 'F' && ata_parm->model[1] == 'X') || (ata_parm->model[0] == 'P' && ata_parm->model[1] == 'i'))) bswap(ata_parm->model, sizeof(ata_parm->model)); btrim(ata_parm->model, sizeof(ata_parm->model)); bpack(ata_parm->model, ata_parm->model, sizeof(ata_parm->model)); bswap(ata_parm->revision, sizeof(ata_parm->revision)); btrim(ata_parm->revision, sizeof(ata_parm->revision)); bpack(ata_parm->revision, ata_parm->revision, sizeof(ata_parm->revision)); bswap(ata_parm->serial, sizeof(ata_parm->serial)); btrim(ata_parm->serial, sizeof(ata_parm->serial)); bpack(ata_parm->serial, ata_parm->serial, sizeof(ata_parm->serial)); atadev->param = ata_parm; return 0; }
/* **************************************************************** * Inicializa o DMA para os Controladores PATA * **************************************************************** */ void ata_sis_pata_setmode (PCIDATA *pci, ATA_DEVICE *adp, int mode) { ATA_PCI_CTLR *ctlrp = pci->pci_dev_info_ptr; const ATA_CHIP_ID *idp = ctlrp->ac_idp; int devno; devno = (adp->ad_channel->ch_unit << 1) + adp->ad_devno; mode = ata_limit_mode (adp, mode, idp->ch_max_dma); if (idp->ch_cfg1 == SIS133NEW) { if (mode > ATA_UDMA2 && pci_read (pci, adp->ad_channel->ch_unit ? 0x52 : 0x50, 2) & 0x8000) { mode = ATA_UDMA2; printf ("ata[%d,%d]: DMA limitado a %s\n", ATA_DEVNO, ata_dmamode_to_str (mode)); } } else { if (mode > ATA_UDMA2 && pci_read (pci, 0x48, 1) & (adp->ad_channel->ch_unit ? 0x20 : 0x10)) { mode = ATA_UDMA2; printf ("ata[%d,%d]: DMA limitado a %s\n", ATA_DEVNO, ata_dmamode_to_str (mode)); } } if (ata_command (adp, ATA_C_SETFEATURES, 0, mode, ATA_C_F_SETXFER, 0)) return; switch (idp->ch_cfg1) { case SIS133NEW: { ulong timings[] = { 0x28269008, 0x0c266008, 0x04263008, 0x0c0a3008, 0x05093008, 0x22196008, 0x0c0a3008, 0x05093008, 0x050939fc, 0x050936ac, 0x0509347c, 0x0509325c, 0x0509323c, 0x0509322c, 0x0509321c }; ulong reg; reg = (pci_read (pci, 0x57, 1) & 0x40?0x70 : 0x40) + (devno << 2); pci_write (pci, reg, timings[ata_mode2idx (mode)], 4); break; } case SIS133OLD: { ushort timings[] = { 0x00cb, 0x0067, 0x0044, 0x0033, 0x0031, 0x0044, 0x0033, 0x0031, 0x8f31, 0x8a31, 0x8731, 0x8531, 0x8331, 0x8231, 0x8131 }; ushort reg = 0x40 + (devno << 1); pci_write (pci, reg, timings[ata_mode2idx (mode)], 2); break; } case SIS100NEW: { ushort timings[] = { 0x00cb, 0x0067, 0x0044, 0x0033, 0x0031, 0x0044, 0x0033, 0x0031, 0x8b31, 0x8731, 0x8531, 0x8431, 0x8231, 0x8131 }; ushort reg = 0x40 + (devno << 1); pci_write (pci, reg, timings[ata_mode2idx (mode)], 2); break; } case SIS100OLD: case SIS66: case SIS33: { ushort timings[] = { 0x0c0b, 0x0607, 0x0404, 0x0303, 0x0301, 0x0404, 0x0303, 0x0301, 0xf301, 0xd301, 0xb301, 0xa301, 0x9301, 0x8301 }; ushort reg = 0x40 + (devno << 1); pci_write (pci, reg, timings[ata_mode2idx (mode)], 2); break; } } adp->ad_transfer_mode = mode; } /* end ata_sis_pata_setmode */
/* must be called with ATA channel locked */ static int ata_transaction(struct ata_request *request) { /* safety check, device might have been detached FIXME SOS */ if (!request->device->param) { request->result = ENXIO; return ATA_OP_FINISHED; } /* record the request as running */ request->device->channel->running = request; ATA_DEBUG_RQ(request, "transaction"); /* disable ATAPI DMA writes if HW doesn't support it */ if ((request->device->channel->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))) request->flags &= ~ATA_R_DMA; switch (request->flags & (ATA_R_ATAPI | ATA_R_DMA)) { /* ATA PIO data transfer and control commands */ default: { /* record command direction here as our request might be gone later */ int write = (request->flags & ATA_R_WRITE); /* issue command */ if (ata_command(request->device, request->u.ata.command, request->u.ata.lba, request->u.ata.count, request->u.ata.feature)) { ata_prtdev(request->device, "error issueing PIO command\n"); request->result = EIO; break; } /* if write command output the data */ if (write) { if (ata_wait(request->device, (ATA_S_READY | ATA_S_DSC | ATA_S_DRQ)) < 0) { ata_prtdev(request->device,"timeout waiting for write DRQ"); request->result = EIO; break; } ata_pio_write(request, request->transfersize); } } /* return and wait for interrupt */ return ATA_OP_CONTINUES; /* ATA DMA data transfer commands */ case ATA_R_DMA: /* check sanity, setup SG list and DMA engine */ if (request->device->channel->dma->load(request->device, request->data, request->bytecount, request->flags & ATA_R_READ)) { ata_prtdev(request->device, "setting up DMA failed\n"); request->result = EIO; break; } /* issue command */ if (ata_command(request->device, request->u.ata.command, request->u.ata.lba, request->u.ata.count, request->u.ata.feature)) { ata_prtdev(request->device, "error issuing DMA command\n"); request->result = EIO; break; } /* start DMA engine */ if (request->device->channel->dma->start(request->device->channel)) { ata_prtdev(request->device, "error starting DMA\n"); request->result = EIO; break; } /* return and wait for interrupt */ return ATA_OP_CONTINUES; /* ATAPI PIO commands */ case ATA_R_ATAPI: /* is this just a POLL DSC command ? */ if (request->u.atapi.ccb[0] == ATAPI_POLL_DSC) { ATA_IDX_OUTB(request->device->channel, ATA_DRIVE, ATA_D_IBM | request->device->unit); DELAY(10); if (!(ATA_IDX_INB(request->device->channel, ATA_ALTSTAT)&ATA_S_DSC)) request->result = EBUSY; break; } /* start ATAPI operation */ if (ata_command(request->device, ATA_PACKET_CMD, request->transfersize << 8, 0, 0)) { ata_prtdev(request->device, "error issuing ATA PACKET command\n"); request->result = EIO; break; } /* command interrupt device ? just return and wait for interrupt */ if ((request->device->param->config & ATA_DRQ_MASK) == ATA_DRQ_INTR) return ATA_OP_CONTINUES; /* wait for ready to write ATAPI command block */ { int timeout = 5000; /* might be less for fast devices */ while (timeout--) { int reason = ATA_IDX_INB(request->device->channel, ATA_IREASON); int status = ATA_IDX_INB(request->device->channel, ATA_STATUS); if (((reason & (ATA_I_CMD | ATA_I_IN)) | (status & (ATA_S_DRQ | ATA_S_BUSY))) == ATAPI_P_CMDOUT) break; DELAY(20); } if (timeout <= 0) { ata_prtdev(request->device, "timeout waiting for ATAPI ready\n"); request->result = EIO; break; } } /* this seems to be needed for some (slow) devices */ DELAY(10); /* output actual command block */ ATA_IDX_OUTSW_STRM(request->device->channel, ATA_DATA, (int16_t *)request->u.atapi.ccb, (request->device->param->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12 ? 6 : 8); /* return and wait for interrupt */ return ATA_OP_CONTINUES; case ATA_R_ATAPI|ATA_R_DMA: /* is this just a POLL DSC command ? */ if (request->u.atapi.ccb[0] == ATAPI_POLL_DSC) { ATA_IDX_OUTB(request->device->channel, ATA_DRIVE, ATA_D_IBM | request->device->unit); DELAY(10); if (!(ATA_IDX_INB(request->device->channel, ATA_ALTSTAT)&ATA_S_DSC)) request->result = EBUSY; break; } /* check sanity, setup SG list and DMA engine */ if (request->device->channel->dma->load(request->device, request->data, request->bytecount, request->flags & ATA_R_READ)) { ata_prtdev(request->device, "setting up DMA failed\n"); request->result = EIO; break; } /* start ATAPI operation */ if (ata_command(request->device, ATA_PACKET_CMD, 0, 0, ATA_F_DMA)) { ata_prtdev(request->device, "error issuing ATAPI packet command\n"); request->result = EIO; break; } /* wait for ready to write ATAPI command block */ { int timeout = 5000; /* might be less for fast devices */ while (timeout--) { int reason = ATA_IDX_INB(request->device->channel, ATA_IREASON); int status = ATA_IDX_INB(request->device->channel, ATA_STATUS); if (((reason & (ATA_I_CMD | ATA_I_IN)) | (status & (ATA_S_DRQ | ATA_S_BUSY))) == ATAPI_P_CMDOUT) break; DELAY(20); } if (timeout <= 0) { ata_prtdev(request->device,"timeout waiting for ATAPI ready\n"); request->result = EIO; break; } } /* this seems to be needed for some (slow) devices */ DELAY(10); /* output actual command block */ ATA_IDX_OUTSW_STRM(request->device->channel, ATA_DATA, (int16_t *)request->u.atapi.ccb, (request->device->param->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12 ? 6 : 8); /* start DMA engine */ if (request->device->channel->dma->start(request->device->channel)) { request->result = EIO; break; } /* return and wait for interrupt */ return ATA_OP_CONTINUES; } /* request finish here */ if (request->device->channel->dma->flags & ATA_DMA_ACTIVE) request->device->channel->dma->unload(request->device->channel); request->device->channel->running = NULL; return ATA_OP_FINISHED; }