[BACK]Return to ahcisata_core.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / ic

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/dev/ic/ahcisata_core.c between version 1.14.4.4 and 1.14.4.5

version 1.14.4.4, 2010/03/11 15:03:28 version 1.14.4.5, 2010/08/11 22:53:22
Line 39  __KERNEL_RCSID(0, "$NetBSD$");
Line 39  __KERNEL_RCSID(0, "$NetBSD$");
   
 #include <uvm/uvm_extern.h>  #include <uvm/uvm_extern.h>
   
 #include <dev/ic/wdcreg.h>  
 #include <dev/ata/atareg.h>  #include <dev/ata/atareg.h>
 #include <dev/ata/satavar.h>  #include <dev/ata/satavar.h>
 #include <dev/ata/satareg.h>  #include <dev/ata/satareg.h>
 #include <dev/ata/satafisreg.h>  
 #include <dev/ata/satafisvar.h>  #include <dev/ata/satafisvar.h>
   #include <dev/ata/satafisreg.h>
 #include <dev/ic/ahcisatavar.h>  #include <dev/ic/ahcisatavar.h>
   
 #include <dev/scsipi/scsi_all.h> /* for SCSI status */  #include <dev/scsipi/scsi_all.h> /* for SCSI status */
Line 55  __KERNEL_RCSID(0, "$NetBSD$");
Line 54  __KERNEL_RCSID(0, "$NetBSD$");
 int ahcidebug_mask = 0x0;  int ahcidebug_mask = 0x0;
 #endif  #endif
   
 void ahci_probe_drive(struct ata_channel *);  static void ahci_probe_drive(struct ata_channel *);
 void ahci_setup_channel(struct ata_channel *);  static void ahci_setup_channel(struct ata_channel *);
   
 int  ahci_ata_bio(struct ata_drive_datas *, struct ata_bio *);  static int  ahci_ata_bio(struct ata_drive_datas *, struct ata_bio *);
 void ahci_reset_drive(struct ata_drive_datas *, int);  static void ahci_reset_drive(struct ata_drive_datas *, int);
 void ahci_reset_channel(struct ata_channel *, int);  static void ahci_reset_channel(struct ata_channel *, int);
 int  ahci_exec_command(struct ata_drive_datas *, struct ata_command *);  static int  ahci_exec_command(struct ata_drive_datas *, struct ata_command *);
 int  ahci_ata_addref(struct ata_drive_datas *);  static int  ahci_ata_addref(struct ata_drive_datas *);
 void ahci_ata_delref(struct ata_drive_datas *);  static void ahci_ata_delref(struct ata_drive_datas *);
 void ahci_killpending(struct ata_drive_datas *);  static void ahci_killpending(struct ata_drive_datas *);
   
 void ahci_cmd_start(struct ata_channel *, struct ata_xfer *);  static void ahci_cmd_start(struct ata_channel *, struct ata_xfer *);
 int  ahci_cmd_complete(struct ata_channel *, struct ata_xfer *, int);  static int  ahci_cmd_complete(struct ata_channel *, struct ata_xfer *, int);
 void ahci_cmd_done(struct ata_channel *, struct ata_xfer *, int);  static void ahci_cmd_done(struct ata_channel *, struct ata_xfer *, int);
 void ahci_cmd_kill_xfer(struct ata_channel *, struct ata_xfer *, int) ;  static void ahci_cmd_kill_xfer(struct ata_channel *, struct ata_xfer *, int) ;
 void ahci_bio_start(struct ata_channel *, struct ata_xfer *);  static void ahci_bio_start(struct ata_channel *, struct ata_xfer *);
 int  ahci_bio_complete(struct ata_channel *, struct ata_xfer *, int);  static int  ahci_bio_complete(struct ata_channel *, struct ata_xfer *, int);
 void ahci_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int) ;  static void ahci_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int) ;
 void ahci_channel_stop(struct ahci_softc *, struct ata_channel *, int);  static void ahci_channel_stop(struct ahci_softc *, struct ata_channel *, int);
 void ahci_channel_start(struct ahci_softc *, struct ata_channel *);  static void ahci_channel_start(struct ahci_softc *, struct ata_channel *);
 void ahci_timeout(void *);  static void ahci_timeout(void *);
 int  ahci_dma_setup(struct ata_channel *, int, void *, size_t, int);  static int  ahci_dma_setup(struct ata_channel *, int, void *, size_t, int);
   
 #if NATAPIBUS > 0  #if NATAPIBUS > 0
 void ahci_atapibus_attach(struct atabus_softc *);  static void ahci_atapibus_attach(struct atabus_softc *);
 void ahci_atapi_kill_pending(struct scsipi_periph *);  static void ahci_atapi_kill_pending(struct scsipi_periph *);
 void ahci_atapi_minphys(struct buf *);  static void ahci_atapi_minphys(struct buf *);
 void ahci_atapi_scsipi_request(struct scsipi_channel *,  static void ahci_atapi_scsipi_request(struct scsipi_channel *,
     scsipi_adapter_req_t, void *);      scsipi_adapter_req_t, void *);
 void ahci_atapi_start(struct ata_channel *, struct ata_xfer *);  static void ahci_atapi_start(struct ata_channel *, struct ata_xfer *);
 int  ahci_atapi_complete(struct ata_channel *, struct ata_xfer *, int);  static int  ahci_atapi_complete(struct ata_channel *, struct ata_xfer *, int);
 void ahci_atapi_kill_xfer(struct ata_channel *, struct ata_xfer *, int);  static void ahci_atapi_kill_xfer(struct ata_channel *, struct ata_xfer *, int);
 void ahci_atapi_probe_device(struct atapibus_softc *, int);  static void ahci_atapi_probe_device(struct atapibus_softc *, int);
   
 static const struct scsipi_bustype ahci_atapi_bustype = {  static const struct scsipi_bustype ahci_atapi_bustype = {
         SCSIPI_BUSTYPE_ATAPI,          SCSIPI_BUSTYPE_ATAPI,
Line 99  static const struct scsipi_bustype ahci_
Line 98  static const struct scsipi_bustype ahci_
 #endif /* NATAPIBUS */  #endif /* NATAPIBUS */
   
 #define ATA_DELAY 10000 /* 10s for a drive I/O */  #define ATA_DELAY 10000 /* 10s for a drive I/O */
   #define ATA_RESET_DELAY 31000 /* 31s for a drive reset */
   #define AHCI_RST_WAIT (ATA_RESET_DELAY / 10)
   
 const struct ata_bustype ahci_ata_bustype = {  const struct ata_bustype ahci_ata_bustype = {
         SCSIPI_BUSTYPE_ATA,          SCSIPI_BUSTYPE_ATA,
Line 112  const struct ata_bustype ahci_ata_bustyp
Line 113  const struct ata_bustype ahci_ata_bustyp
         ahci_killpending          ahci_killpending
 };  };
   
 void ahci_intr_port(struct ahci_softc *, struct ahci_channel *);  static void ahci_intr_port(struct ahci_softc *, struct ahci_channel *);
   
 static void ahci_setup_port(struct ahci_softc *sc, int i);  static void ahci_setup_port(struct ahci_softc *sc, int i);
   
 int  static int
 ahci_reset(struct ahci_softc *sc)  ahci_reset(struct ahci_softc *sc)
 {  {
         int i;          int i;
Line 138  ahci_reset(struct ahci_softc *sc)
Line 138  ahci_reset(struct ahci_softc *sc)
         return 0;          return 0;
 }  }
   
 void  static void
 ahci_setup_ports(struct ahci_softc *sc)  ahci_setup_ports(struct ahci_softc *sc)
 {  {
         u_int32_t ahci_ports;          uint32_t ahci_ports;
         int i, port;          int i, port;
   
         ahci_ports = AHCI_READ(sc, AHCI_PI);          ahci_ports = AHCI_READ(sc, AHCI_PI);
Line 157  ahci_setup_ports(struct ahci_softc *sc)
Line 157  ahci_setup_ports(struct ahci_softc *sc)
         }          }
 }  }
   
 void  static void
 ahci_reprobe_drives(struct ahci_softc *sc)  ahci_reprobe_drives(struct ahci_softc *sc)
 {  {
         u_int32_t ahci_ports;          uint32_t ahci_ports;
         int i, port;          int i, port;
         struct ahci_channel *achp;          struct ahci_channel *achp;
         struct ata_channel *chp;          struct ata_channel *chp;
Line 189  ahci_setup_port(struct ahci_softc *sc, i
Line 189  ahci_setup_port(struct ahci_softc *sc, i
         achp = &sc->sc_channels[i];          achp = &sc->sc_channels[i];
   
         AHCI_WRITE(sc, AHCI_P_CLB(i), achp->ahcic_bus_cmdh);          AHCI_WRITE(sc, AHCI_P_CLB(i), achp->ahcic_bus_cmdh);
         AHCI_WRITE(sc, AHCI_P_CLBU(i), 0);          AHCI_WRITE(sc, AHCI_P_CLBU(i), (uint64_t)achp->ahcic_bus_cmdh>>32);
         AHCI_WRITE(sc, AHCI_P_FB(i), achp->ahcic_bus_rfis);          AHCI_WRITE(sc, AHCI_P_FB(i), achp->ahcic_bus_rfis);
         AHCI_WRITE(sc, AHCI_P_FBU(i), 0);          AHCI_WRITE(sc, AHCI_P_FBU(i), (uint64_t)achp->ahcic_bus_rfis>>32);
 }  }
   
 void  static void
 ahci_enable_intrs(struct ahci_softc *sc)  ahci_enable_intrs(struct ahci_softc *sc)
 {  {
   
Line 207  ahci_enable_intrs(struct ahci_softc *sc)
Line 207  ahci_enable_intrs(struct ahci_softc *sc)
 void  void
 ahci_attach(struct ahci_softc *sc)  ahci_attach(struct ahci_softc *sc)
 {  {
         u_int32_t ahci_cap, ahci_rev, ahci_ports;          uint32_t ahci_cap, ahci_rev, ahci_ports;
         int i, j, port;          int i, j, port;
         struct ahci_channel *achp;          struct ahci_channel *achp;
         struct ata_channel *chp;          struct ata_channel *chp;
         int error;          int error;
         bus_dma_segment_t seg;  
         int rseg;  
         int dmasize;          int dmasize;
         void *cmdhp;          void *cmdhp;
         void *cmdtblp;          void *cmdtblp;
Line 260  ahci_attach(struct ahci_softc *sc)
Line 258  ahci_attach(struct ahci_softc *sc)
         dmasize =          dmasize =
             (AHCI_RFIS_SIZE + AHCI_CMDH_SIZE) * sc->sc_atac.atac_nchannels;              (AHCI_RFIS_SIZE + AHCI_CMDH_SIZE) * sc->sc_atac.atac_nchannels;
         error = bus_dmamem_alloc(sc->sc_dmat, dmasize, PAGE_SIZE, 0,          error = bus_dmamem_alloc(sc->sc_dmat, dmasize, PAGE_SIZE, 0,
             &seg, 1, &rseg, BUS_DMA_NOWAIT);              &sc->sc_cmd_hdr_seg, 1, &sc->sc_cmd_hdr_nseg, BUS_DMA_NOWAIT);
         if (error) {          if (error) {
                 aprint_error("%s: unable to allocate command header memory"                  aprint_error("%s: unable to allocate command header memory"
                     ", error=%d\n", AHCINAME(sc), error);                      ", error=%d\n", AHCINAME(sc), error);
                 return;                  return;
         }          }
         error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, dmasize,          error = bus_dmamem_map(sc->sc_dmat, &sc->sc_cmd_hdr_seg,
               sc->sc_cmd_hdr_nseg, dmasize,
             &cmdhp, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);              &cmdhp, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
         if (error) {          if (error) {
                 aprint_error("%s: unable to map command header memory"                  aprint_error("%s: unable to map command header memory"
Line 301  ahci_attach(struct ahci_softc *sc)
Line 300  ahci_attach(struct ahci_softc *sc)
                         break;                          break;
                 }                  }
                 achp = &sc->sc_channels[i];                  achp = &sc->sc_channels[i];
                 chp = (struct ata_channel *)achp;                  chp = &achp->ata_channel;
                 sc->sc_chanarray[i] = chp;                  sc->sc_chanarray[i] = chp;
                 chp->ch_channel = i;                  chp->ch_channel = i;
                 chp->ch_atac = &sc->sc_atac;                  chp->ch_atac = &sc->sc_atac;
Line 314  ahci_attach(struct ahci_softc *sc)
Line 313  ahci_attach(struct ahci_softc *sc)
                 }                  }
                 dmasize = AHCI_CMDTBL_SIZE * sc->sc_ncmds;                  dmasize = AHCI_CMDTBL_SIZE * sc->sc_ncmds;
                 error = bus_dmamem_alloc(sc->sc_dmat, dmasize, PAGE_SIZE, 0,                  error = bus_dmamem_alloc(sc->sc_dmat, dmasize, PAGE_SIZE, 0,
                     &seg, 1, &rseg, BUS_DMA_NOWAIT);                      &achp->ahcic_cmd_tbl_seg, 1, &achp->ahcic_cmd_tbl_nseg,
                       BUS_DMA_NOWAIT);
                 if (error) {                  if (error) {
                         aprint_error("%s: unable to allocate command table "                          aprint_error("%s: unable to allocate command table "
                             "memory, error=%d\n", AHCINAME(sc), error);                              "memory, error=%d\n", AHCINAME(sc), error);
                         break;                          break;
                 }                  }
                 error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, dmasize,                  error = bus_dmamem_map(sc->sc_dmat, &achp->ahcic_cmd_tbl_seg,
                       achp->ahcic_cmd_tbl_nseg, dmasize,
                     &cmdtblp, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);                      &cmdtblp, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
                 if (error) {                  if (error) {
                         aprint_error("%s: unable to map command table memory"                          aprint_error("%s: unable to map command table memory"
Line 352  ahci_attach(struct ahci_softc *sc)
Line 353  ahci_attach(struct ahci_softc *sc)
                 achp->ahcic_bus_rfis = sc->sc_cmd_hdrd->dm_segs[0].ds_addr +                  achp->ahcic_bus_rfis = sc->sc_cmd_hdrd->dm_segs[0].ds_addr +
                      AHCI_CMDH_SIZE * sc->sc_atac.atac_nchannels +                       AHCI_CMDH_SIZE * sc->sc_atac.atac_nchannels +
                      AHCI_RFIS_SIZE * port;                       AHCI_RFIS_SIZE * port;
                 AHCIDEBUG_PRINT(("port %d cmdh %p (0x%x) rfis %p (0x%x)\n", i,                  AHCIDEBUG_PRINT(("port %d cmdh %p (0x%" PRIx64 ") "
                    achp->ahcic_cmdh, (u_int)achp->ahcic_bus_cmdh,                                           "rfis %p (0x%" PRIx64 ")\n", i,
                    achp->ahcic_rfis, (u_int)achp->ahcic_bus_rfis),                     achp->ahcic_cmdh, (uint64_t)achp->ahcic_bus_cmdh,
                      achp->ahcic_rfis, (uint64_t)achp->ahcic_bus_rfis),
                    DEBUG_PROBE);                     DEBUG_PROBE);
   
                 for (j = 0; j < sc->sc_ncmds; j++) {                  for (j = 0; j < sc->sc_ncmds; j++) {
Line 364  ahci_attach(struct ahci_softc *sc)
Line 366  ahci_attach(struct ahci_softc *sc)
                              achp->ahcic_cmd_tbld->dm_segs[0].ds_addr +                               achp->ahcic_cmd_tbld->dm_segs[0].ds_addr +
                              AHCI_CMDTBL_SIZE * j;                               AHCI_CMDTBL_SIZE * j;
                         achp->ahcic_cmdh[j].cmdh_cmdtba =                          achp->ahcic_cmdh[j].cmdh_cmdtba =
                             htole32(achp->ahcic_bus_cmd_tbl[j]);                              htole64(achp->ahcic_bus_cmd_tbl[j]);
                         achp->ahcic_cmdh[j].cmdh_cmdtbau = htole32(0);                          AHCIDEBUG_PRINT(("port %d/%d tbl %p (0x%" PRIx64 ")\n", i, j,
                         AHCIDEBUG_PRINT(("port %d/%d tbl %p (0x%x)\n", i, j,  
                             achp->ahcic_cmd_tbl[j],                              achp->ahcic_cmd_tbl[j],
                             (u_int)achp->ahcic_bus_cmd_tbl[j]), DEBUG_PROBE);                              (uint64_t)achp->ahcic_bus_cmd_tbl[j]), DEBUG_PROBE);
                         /* The xfer DMA map */                          /* The xfer DMA map */
                         error = bus_dmamap_create(sc->sc_dmat, MAXPHYS,                          error = bus_dmamap_create(sc->sc_dmat, MAXPHYS,
                             AHCI_NPRD, 0x400000 /* 4MB */, 0,                              AHCI_NPRD, 0x400000 /* 4MB */, 0,
Line 408  end:
Line 409  end:
 }  }
   
 int  int
   ahci_detach(struct ahci_softc *sc, int flags)
   {
           struct atac_softc *atac;
           struct ahci_channel *achp;
           struct ata_channel *chp;
           struct scsipi_adapter *adapt;
           uint32_t ahci_ports;
           int i, j;
           int error;
   
           atac = &sc->sc_atac;
           adapt = &atac->atac_atapi_adapter._generic;
   
           ahci_ports = AHCI_READ(sc, AHCI_PI);
           for (i = 0; i < AHCI_MAX_PORTS; i++) {
                   achp = &sc->sc_channels[i];
                   chp = &achp->ata_channel;
   
                   if ((ahci_ports & (1 << i)) == 0)
                           continue;
                   if (i >= sc->sc_atac.atac_nchannels) {
                           aprint_error("%s: more ports than announced\n",
                               AHCINAME(sc));
                           break;
                   }
   
                   if (chp->atabus == NULL)
                           continue;
                   if ((error = config_detach(chp->atabus, flags)) != 0)
                           return error;
   
                   for (j = 0; j < sc->sc_ncmds; j++)
                           bus_dmamap_destroy(sc->sc_dmat, achp->ahcic_datad[j]);
   
                   bus_dmamap_unload(sc->sc_dmat, achp->ahcic_cmd_tbld);
                   bus_dmamap_destroy(sc->sc_dmat, achp->ahcic_cmd_tbld);
                   bus_dmamem_unmap(sc->sc_dmat, achp->ahcic_cmd_tbl[0],
                       AHCI_CMDTBL_SIZE * sc->sc_ncmds);
                   bus_dmamem_free(sc->sc_dmat, &achp->ahcic_cmd_tbl_seg,
                       achp->ahcic_cmd_tbl_nseg);
   
                   free(chp->ch_queue, M_DEVBUF);
                   chp->atabus = NULL;
           }
   
           bus_dmamap_unload(sc->sc_dmat, sc->sc_cmd_hdrd);
           bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmd_hdrd);
           bus_dmamem_unmap(sc->sc_dmat, sc->sc_cmd_hdr,
               (AHCI_RFIS_SIZE + AHCI_CMDH_SIZE) * sc->sc_atac.atac_nchannels);
           bus_dmamem_free(sc->sc_dmat, &sc->sc_cmd_hdr_seg, sc->sc_cmd_hdr_nseg);
   
           if (adapt->adapt_refcnt != 0)
                   return EBUSY;
   
           return 0;
   }
   
   void
   ahci_resume(struct ahci_softc *sc)
   {
           ahci_reset(sc);
           ahci_setup_ports(sc);
           ahci_reprobe_drives(sc);
           ahci_enable_intrs(sc);
   }
   
   int
 ahci_intr(void *v)  ahci_intr(void *v)
 {  {
         struct ahci_softc *sc = v;          struct ahci_softc *sc = v;
         u_int32_t is;          uint32_t is;
         int i, r = 0;          int i, r = 0;
   
         while ((is = AHCI_READ(sc, AHCI_IS))) {          while ((is = AHCI_READ(sc, AHCI_IS))) {
Line 426  ahci_intr(void *v)
Line 494  ahci_intr(void *v)
         return r;          return r;
 }  }
   
 void  static void
 ahci_intr_port(struct ahci_softc *sc, struct ahci_channel *achp)  ahci_intr_port(struct ahci_softc *sc, struct ahci_channel *achp)
 {  {
         u_int32_t is, tfd;          uint32_t is, tfd;
         struct ata_channel *chp = &achp->ata_channel;          struct ata_channel *chp = &achp->ata_channel;
         struct ata_xfer *xfer = chp->ch_queue->active_xfer;          struct ata_xfer *xfer = chp->ch_queue->active_xfer;
         int slot;          int slot;
Line 482  ahci_intr_port(struct ahci_softc *sc, st
Line 550  ahci_intr_port(struct ahci_softc *sc, st
         }          }
 }  }
   
 void  static void
 ahci_reset_drive(struct ata_drive_datas *drvp, int flags)  ahci_reset_drive(struct ata_drive_datas *drvp, int flags)
 {  {
         struct ata_channel *chp = drvp->chnl_softc;          struct ata_channel *chp = drvp->chnl_softc;
Line 490  ahci_reset_drive(struct ata_drive_datas 
Line 558  ahci_reset_drive(struct ata_drive_datas 
         return;          return;
 }  }
   
 void  static void
 ahci_reset_channel(struct ata_channel *chp, int flags)  ahci_reset_channel(struct ata_channel *chp, int flags)
 {  {
         struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;          struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
Line 507  ahci_reset_channel(struct ata_channel *c
Line 575  ahci_reset_channel(struct ata_channel *c
                 chp->ch_queue->active_xfer->c_kill_xfer(chp,                  chp->ch_queue->active_xfer->c_kill_xfer(chp,
                     chp->ch_queue->active_xfer, KILL_RESET);                      chp->ch_queue->active_xfer, KILL_RESET);
         }          }
           tsleep(&sc, PRIBIO, "ahcirst", mstohz(500));
           /* clear port interrupt register */
           AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);
           /* clear SErrors and start operations */
           ahci_channel_start(sc, chp);
         /* wait 31s for BSY to clear */          /* wait 31s for BSY to clear */
         for (i = 0; i <3100; i++) {          for (i = 0; i <AHCI_RST_WAIT; i++) {
                 tfd = AHCI_READ(sc, AHCI_P_TFD(chp->ch_channel));                  tfd = AHCI_READ(sc, AHCI_P_TFD(chp->ch_channel));
                 if ((((tfd & AHCI_P_TFD_ST) >> AHCI_P_TFD_ST_SHIFT)                  if ((((tfd & AHCI_P_TFD_ST) >> AHCI_P_TFD_ST_SHIFT)
                     & WDCS_BSY) == 0)                      & WDCS_BSY) == 0)
                         break;                          break;
                 tsleep(&sc, PRIBIO, "ahcid2h", mstohz(10));                  tsleep(&sc, PRIBIO, "ahcid2h", mstohz(10));
         }          }
         if (i == 1500)          if (i == AHCI_RST_WAIT)
                 aprint_error("%s: BSY never cleared, TD 0x%x\n",                  aprint_error("%s: BSY never cleared, TD 0x%x\n",
                     AHCINAME(sc), tfd);                      AHCINAME(sc), tfd);
         AHCIDEBUG_PRINT(("%s: BSY took %d ms\n", AHCINAME(sc), i * 10),          AHCIDEBUG_PRINT(("%s: BSY took %d ms\n", AHCINAME(sc), i * 10),
             DEBUG_PROBE);              DEBUG_PROBE);
         /* clear port interrupt register */          /* clear port interrupt register */
         AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);          AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);
         /* and start channel */  
         ahci_channel_start(sc, chp);  
   
         return;          return;
 }  }
   
 int  static int
 ahci_ata_addref(struct ata_drive_datas *drvp)  ahci_ata_addref(struct ata_drive_datas *drvp)
 {  {
         return 0;          return 0;
 }  }
   
 void  static void
 ahci_ata_delref(struct ata_drive_datas *drvp)  ahci_ata_delref(struct ata_drive_datas *drvp)
 {  {
         return;          return;
 }  }
   
 void  static void
 ahci_killpending(struct ata_drive_datas *drvp)  ahci_killpending(struct ata_drive_datas *drvp)
 {  {
         return;          return;
 }  }
   
 void  static void
 ahci_probe_drive(struct ata_channel *chp)  ahci_probe_drive(struct ata_channel *chp)
 {  {
         struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;          struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
         struct ahci_channel *achp = (struct ahci_channel *)chp;          struct ahci_channel *achp = (struct ahci_channel *)chp;
         int i, s;          int i, s;
         u_int32_t sig;          uint32_t sig;
   
         /* XXX This should be done by other code. */          /* XXX This should be done by other code. */
         for (i = 0; i < chp->ch_ndrive; i++) {          for (i = 0; i < chp->ch_ndrive; i++) {
Line 568  ahci_probe_drive(struct ata_channel *chp
Line 639  ahci_probe_drive(struct ata_channel *chp
         switch (sata_reset_interface(chp, sc->sc_ahcit, achp->ahcic_scontrol,          switch (sata_reset_interface(chp, sc->sc_ahcit, achp->ahcic_scontrol,
             achp->ahcic_sstatus)) {              achp->ahcic_sstatus)) {
         case SStatus_DET_DEV:          case SStatus_DET_DEV:
                   tsleep(&sc, PRIBIO, "ahcidv", mstohz(500));
                   /* clear port interrupt register */
                   AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);
                   /* clear SErrors and start operations */
                   ahci_channel_start(sc, chp);
                 /* wait 31s for BSY to clear */                  /* wait 31s for BSY to clear */
                 for (i = 0; i <3100; i++) {                  for (i = 0; i <AHCI_RST_WAIT; i++) {
                         sig = AHCI_READ(sc, AHCI_P_TFD(chp->ch_channel));                          sig = AHCI_READ(sc, AHCI_P_TFD(chp->ch_channel));
                         if ((((sig & AHCI_P_TFD_ST) >> AHCI_P_TFD_ST_SHIFT)                          if ((((sig & AHCI_P_TFD_ST) >> AHCI_P_TFD_ST_SHIFT)
                             & WDCS_BSY) == 0)                              & WDCS_BSY) == 0)
                                 break;                                  break;
                         tsleep(&sc, PRIBIO, "ahcid2h", mstohz(10));                          tsleep(&sc, PRIBIO, "ahcid2h", mstohz(10));
                 }                  }
                 if (i == 1500) {                  if (i == AHCI_RST_WAIT) {
                         aprint_error("%s: BSY never cleared, TD 0x%x\n",                          aprint_error("%s: BSY never cleared, TD 0x%x\n",
                             AHCINAME(sc), sig);                              AHCINAME(sc), sig);
                         return;                          return;
Line 599  ahci_probe_drive(struct ata_channel *chp
Line 675  ahci_probe_drive(struct ata_channel *chp
                 splx(s);                  splx(s);
                 /* clear port interrupt register */                  /* clear port interrupt register */
                 AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);                  AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);
                 /* start channel */  
                 ahci_channel_start(sc, chp);  
                 /* and enable interrupts */                  /* and enable interrupts */
                 AHCI_WRITE(sc, AHCI_P_IE(chp->ch_channel),                  AHCI_WRITE(sc, AHCI_P_IE(chp->ch_channel),
                     AHCI_P_IX_TFES | AHCI_P_IX_HBFS | AHCI_P_IX_IFS |                      AHCI_P_IX_TFES | AHCI_P_IX_HBFS | AHCI_P_IX_IFS |
Line 615  ahci_probe_drive(struct ata_channel *chp
Line 689  ahci_probe_drive(struct ata_channel *chp
         }          }
 }  }
   
 void  static void
 ahci_setup_channel(struct ata_channel *chp)  ahci_setup_channel(struct ata_channel *chp)
 {  {
         return;          return;
 }  }
   
 int  static int
 ahci_exec_command(struct ata_drive_datas *drvp, struct ata_command *ata_c)  ahci_exec_command(struct ata_drive_datas *drvp, struct ata_command *ata_c)
 {  {
         struct ata_channel *chp = drvp->chnl_softc;          struct ata_channel *chp = drvp->chnl_softc;
Line 672  ahci_exec_command(struct ata_drive_datas
Line 746  ahci_exec_command(struct ata_drive_datas
         return ret;          return ret;
 }  }
   
 void  static void
 ahci_cmd_start(struct ata_channel *chp, struct ata_xfer *xfer)  ahci_cmd_start(struct ata_channel *chp, struct ata_xfer *xfer)
 {  {
         struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;          struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
Line 755  ahci_cmd_start(struct ata_channel *chp, 
Line 829  ahci_cmd_start(struct ata_channel *chp, 
         AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE);          AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE);
 }  }
   
 void  static void
 ahci_cmd_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason)  ahci_cmd_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason)
 {  {
         struct ata_command *ata_c = xfer->c_cmd;          struct ata_command *ata_c = xfer->c_cmd;
Line 776  ahci_cmd_kill_xfer(struct ata_channel *c
Line 850  ahci_cmd_kill_xfer(struct ata_channel *c
         ahci_cmd_done(chp, xfer, 0 /* XXX slot */);          ahci_cmd_done(chp, xfer, 0 /* XXX slot */);
 }  }
   
 int  static int
 ahci_cmd_complete(struct ata_channel *chp, struct ata_xfer *xfer, int is)  ahci_cmd_complete(struct ata_channel *chp, struct ata_xfer *xfer, int is)
 {  {
         int slot = 0; /* XXX slot */          int slot = 0; /* XXX slot */
         struct ata_command *ata_c = xfer->c_cmd;          struct ata_command *ata_c = xfer->c_cmd;
         struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;          struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
           struct ahci_channel *achp = (struct ahci_channel *)chp;
   
         AHCIDEBUG_PRINT(("ahci_cmd_complete channel %d CMD 0x%x CI 0x%x\n",          AHCIDEBUG_PRINT(("ahci_cmd_complete channel %d CMD 0x%x CI 0x%x\n",
             chp->ch_channel, AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)),              chp->ch_channel, AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)),
Line 801  ahci_cmd_complete(struct ata_channel *ch
Line 876  ahci_cmd_complete(struct ata_channel *ch
                 wakeup(&chp->ch_queue->active_xfer);                  wakeup(&chp->ch_queue->active_xfer);
                 return 0;                  return 0;
         }          }
         if (is) {  
                 ata_c->r_head = 0;          if (chp->ch_status & WDCS_BSY) {
                 ata_c->r_count = 0;                  ata_c->flags |= AT_TIMEOU;
                 ata_c->r_sector = 0;          } else if (chp->ch_status & WDCS_ERR) {
                 ata_c->r_cyl = 0;                  ata_c->r_error = chp->ch_error;
                 if (chp->ch_status & WDCS_BSY) {                  ata_c->flags |= AT_ERROR;
                         ata_c->flags |= AT_TIMEOU;  
                 } else if (chp->ch_status & WDCS_ERR) {  
                         ata_c->r_error = chp->ch_error;  
                         ata_c->flags |= AT_ERROR;  
                 }  
         }          }
   
           if (ata_c->flags & AT_READREG)
                   satafis_rdh_cmd_readreg(ata_c, achp->ahcic_rfis->rfis_rfis);
   
         ahci_cmd_done(chp, xfer, slot);          ahci_cmd_done(chp, xfer, slot);
         return 0;          return 0;
 }  }
   
 void  static void
 ahci_cmd_done(struct ata_channel *chp, struct ata_xfer *xfer, int slot)  ahci_cmd_done(struct ata_channel *chp, struct ata_xfer *xfer, int slot)
 {  {
         struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;          struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
         struct ahci_channel *achp = (struct ahci_channel *)chp;          struct ahci_channel *achp = (struct ahci_channel *)chp;
         struct ata_command *ata_c = xfer->c_cmd;          struct ata_command *ata_c = xfer->c_cmd;
           uint16_t *idwordbuf;
           int i;
   
         AHCIDEBUG_PRINT(("ahci_cmd_done channel %d\n", chp->ch_channel),          AHCIDEBUG_PRINT(("ahci_cmd_done channel %d\n", chp->ch_channel),
             DEBUG_FUNCS);              DEBUG_FUNCS);
Line 841  ahci_cmd_done(struct ata_channel *chp, s
Line 917  ahci_cmd_done(struct ata_channel *chp, s
         AHCI_CMDH_SYNC(sc, achp, slot,          AHCI_CMDH_SYNC(sc, achp, slot,
             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);              BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
   
           /* ata(4) expects IDENTIFY data to be in host endianess */
           if (ata_c->r_command == WDCC_IDENTIFY ||
               ata_c->r_command == ATAPI_IDENTIFY_DEVICE) {
                   idwordbuf = xfer->c_databuf;
                   for (i = 0; i < (xfer->c_bcount / sizeof(*idwordbuf)); i++) {
                           idwordbuf[i] = le16toh(idwordbuf[i]);
                   }
           }
   
         ata_c->flags |= AT_DONE;          ata_c->flags |= AT_DONE;
         if (achp->ahcic_cmdh[slot].cmdh_prdbc)          if (achp->ahcic_cmdh[slot].cmdh_prdbc)
                 ata_c->flags |= AT_XFDONE;                  ata_c->flags |= AT_XFDONE;
Line 854  ahci_cmd_done(struct ata_channel *chp, s
Line 939  ahci_cmd_done(struct ata_channel *chp, s
         return;          return;
 }  }
   
 int  static int
 ahci_ata_bio(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)  ahci_ata_bio(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
 {  {
         struct ata_channel *chp = drvp->chnl_softc;          struct ata_channel *chp = drvp->chnl_softc;
Line 881  ahci_ata_bio(struct ata_drive_datas *drv
Line 966  ahci_ata_bio(struct ata_drive_datas *drv
         return (ata_bio->flags & ATA_ITSDONE) ? ATACMD_COMPLETE : ATACMD_QUEUED;          return (ata_bio->flags & ATA_ITSDONE) ? ATACMD_COMPLETE : ATACMD_QUEUED;
 }  }
   
 void  static void
 ahci_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)  ahci_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)
 {  {
         struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;          struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
Line 963  ahci_bio_start(struct ata_channel *chp, 
Line 1048  ahci_bio_start(struct ata_channel *chp, 
         AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE);          AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE);
 }  }
   
 void  static void
 ahci_bio_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason)  ahci_bio_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason)
 {  {
         int slot = 0;  /* XXX slot */          int slot = 0;  /* XXX slot */
Line 991  ahci_bio_kill_xfer(struct ata_channel *c
Line 1076  ahci_bio_kill_xfer(struct ata_channel *c
         (*chp->ch_drive[drive].drv_done)(chp->ch_drive[drive].drv_softc);          (*chp->ch_drive[drive].drv_done)(chp->ch_drive[drive].drv_softc);
 }  }
   
 int  static int
 ahci_bio_complete(struct ata_channel *chp, struct ata_xfer *xfer, int is)  ahci_bio_complete(struct ata_channel *chp, struct ata_xfer *xfer, int is)
 {  {
         int slot = 0; /* XXX slot */          int slot = 0; /* XXX slot */
Line 1053  ahci_bio_complete(struct ata_channel *ch
Line 1138  ahci_bio_complete(struct ata_channel *ch
         return 0;          return 0;
 }  }
   
 void  static void
 ahci_channel_stop(struct ahci_softc *sc, struct ata_channel *chp, int flags)  ahci_channel_stop(struct ahci_softc *sc, struct ata_channel *chp, int flags)
 {  {
         int i;          int i;
Line 1077  ahci_channel_stop(struct ahci_softc *sc,
Line 1162  ahci_channel_stop(struct ahci_softc *sc,
         }          }
 }  }
   
 void  static void
 ahci_channel_start(struct ahci_softc *sc, struct ata_channel *chp)  ahci_channel_start(struct ahci_softc *sc, struct ata_channel *chp)
 {  {
         /* clear error */          /* clear error */
Line 1090  ahci_channel_start(struct ahci_softc *sc
Line 1175  ahci_channel_start(struct ahci_softc *sc
             AHCI_P_CMD_FRE | AHCI_P_CMD_ST);              AHCI_P_CMD_FRE | AHCI_P_CMD_ST);
 }  }
   
 void  static void
 ahci_timeout(void *v)  ahci_timeout(void *v)
 {  {
         struct ata_channel *chp = (struct ata_channel *)v;          struct ata_channel *chp = (struct ata_channel *)v;
Line 1104  ahci_timeout(void *v)
Line 1189  ahci_timeout(void *v)
         splx(s);          splx(s);
 }  }
   
 int  static int
 ahci_dma_setup(struct ata_channel *chp, int slot, void *data,  ahci_dma_setup(struct ata_channel *chp, int slot, void *data,
     size_t count, int op)      size_t count, int op)
 {  {
Line 1134  ahci_dma_setup(struct ata_channel *chp, 
Line 1219  ahci_dma_setup(struct ata_channel *chp, 
             achp->ahcic_datad[slot]->dm_mapsize,              achp->ahcic_datad[slot]->dm_mapsize,
             (op == BUS_DMA_READ) ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);              (op == BUS_DMA_READ) ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
         for (seg = 0; seg <  achp->ahcic_datad[slot]->dm_nsegs; seg++) {          for (seg = 0; seg <  achp->ahcic_datad[slot]->dm_nsegs; seg++) {
                 cmd_tbl->cmdt_prd[seg].prd_dba = htole32(                  cmd_tbl->cmdt_prd[seg].prd_dba = htole64(
                      achp->ahcic_datad[slot]->dm_segs[seg].ds_addr);                       achp->ahcic_datad[slot]->dm_segs[seg].ds_addr);
                 cmd_tbl->cmdt_prd[seg].prd_dbau = 0;  
                 cmd_tbl->cmdt_prd[seg].prd_dbc = htole32(                  cmd_tbl->cmdt_prd[seg].prd_dbc = htole32(
                     achp->ahcic_datad[slot]->dm_segs[seg].ds_len - 1);                      achp->ahcic_datad[slot]->dm_segs[seg].ds_len - 1);
         }          }
Line 1148  end:
Line 1232  end:
 }  }
   
 #if NATAPIBUS > 0  #if NATAPIBUS > 0
 void  static void
 ahci_atapibus_attach(struct atabus_softc * ata_sc)  ahci_atapibus_attach(struct atabus_softc * ata_sc)
 {  {
         struct ata_channel *chp = ata_sc->sc_chan;          struct ata_channel *chp = ata_sc->sc_chan;
Line 1180  ahci_atapibus_attach(struct atabus_softc
Line 1264  ahci_atapibus_attach(struct atabus_softc
                 atapiprint);                  atapiprint);
 }  }
   
 void  static void
 ahci_atapi_minphys(struct buf *bp)  ahci_atapi_minphys(struct buf *bp)
 {  {
         if (bp->b_bcount > MAXPHYS)          if (bp->b_bcount > MAXPHYS)
Line 1193  ahci_atapi_minphys(struct buf *bp)
Line 1277  ahci_atapi_minphys(struct buf *bp)
  *   *
  * Must be called at splbio().   * Must be called at splbio().
  */   */
 void  static void
 ahci_atapi_kill_pending(struct scsipi_periph *periph)  ahci_atapi_kill_pending(struct scsipi_periph *periph)
 {  {
         struct atac_softc *atac =          struct atac_softc *atac =
Line 1204  ahci_atapi_kill_pending(struct scsipi_pe
Line 1288  ahci_atapi_kill_pending(struct scsipi_pe
         ata_kill_pending(&chp->ch_drive[periph->periph_target]);          ata_kill_pending(&chp->ch_drive[periph->periph_target]);
 }  }
   
 void  static void
 ahci_atapi_scsipi_request(struct scsipi_channel *chan,  ahci_atapi_scsipi_request(struct scsipi_channel *chan,
     scsipi_adapter_req_t req, void *arg)      scsipi_adapter_req_t req, void *arg)
 {  {
Line 1261  ahci_atapi_scsipi_request(struct scsipi_
Line 1345  ahci_atapi_scsipi_request(struct scsipi_
         }          }
 }  }
   
 void  static void
 ahci_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)  ahci_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
 {  {
         struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;          struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
Line 1343  ahci_atapi_start(struct ata_channel *chp
Line 1427  ahci_atapi_start(struct ata_channel *chp
         AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE);          AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE);
 }  }
   
 int  static int
 ahci_atapi_complete(struct ata_channel *chp, struct ata_xfer *xfer, int irq)  ahci_atapi_complete(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
 {  {
         int slot = 0; /* XXX slot */          int slot = 0; /* XXX slot */
Line 1402  ahci_atapi_complete(struct ata_channel *
Line 1486  ahci_atapi_complete(struct ata_channel *
         return 0;          return 0;
 }  }
   
 void  static void
 ahci_atapi_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason)  ahci_atapi_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason)
 {  {
         struct scsipi_xfer *sc_xfer = xfer->c_cmd;          struct scsipi_xfer *sc_xfer = xfer->c_cmd;
Line 1427  ahci_atapi_kill_xfer(struct ata_channel 
Line 1511  ahci_atapi_kill_xfer(struct ata_channel 
         scsipi_done(sc_xfer);          scsipi_done(sc_xfer);
 }  }
   
 void  static void
 ahci_atapi_probe_device(struct atapibus_softc *sc, int target)  ahci_atapi_probe_device(struct atapibus_softc *sc, int target)
 {  {
         struct scsipi_channel *chan = sc->sc_channel;          struct scsipi_channel *chan = sc->sc_channel;

Legend:
Removed from v.1.14.4.4  
changed lines
  Added in v.1.14.4.5

CVSweb <webmaster@jp.NetBSD.org>