Changeset 76 for trunk


Ignore:
Timestamp:
Feb 18, 2011, 10:09:10 PM (14 years ago)
Author:
chris
Message:
  • APM support
  • Generic IOCTL interface for adapter passthrough commands (ATA and ATAPI)
  • Fixes to ATAPI sense data handling
  • Cosmetic changes to debug reporting
  • Fixed missing interrupt enable flag for PIO transfer completions
  • Added command line switch /I to ignore specific adapters
Location:
trunk/src/os2ahci
Files:
3 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/os2ahci/Makefile

    r36 r76  
    5050               -I$(DDK)\base\ibmh \
    5151               -I$(DDK)\base\src\dev\dasd\diskh \
     52               -I$(DDK)\base\src\dev\thinkpad\dockii\apmcalls \
    5253               -I$(CC16)\include
    5354
     
    5758LIB_DIRS     = $(DDK)\base\lib\ \
    5859               $(DDK)\base\src\dev\dasd\devhlp\ \
    59                $(CC16)\lib\ \
     60               $(DDK)\base\src\dev\thinkpad\dockii\apmcalls\ \
     61               $(CC16)\lib\ \
    6062
    6163
     
    6567TARGET   = os2ahci.add
    6668
    67 LIBS     = addcalls dhcalls doscalls slibcep rmcalls
     69LIBS     = addcalls dhcalls doscalls slibcep rmcalls apmcalls
    6870
    69 SRCS     = init.asm libc.c os2ahci.c pci.c ahci.c ata.c atapi.c ctxhook.c
     71SRCS     = init.asm libc.c os2ahci.c pci.c ahci.c ata.c atapi.c ctxhook.c \
     72           apm.c ioctl.c
    7073
    7174OBJS     = init.obj libc.obj os2ahci.obj pci.obj ahci.obj ata.obj atapi.obj \
    72            ctxhook.obj
     75           ctxhook.obj apm.obj ioctl.obj
    7376
    7477INCS     = os2ahci.h ahci.h version.h
     
    8891libc.obj:     libc.c     Makefile $(INCS)
    8992
    90 os2ahci.obj:  os2ahci.c  Makefile $(INCS) bldday.h
     93os2ahci.obj:  os2ahci.c  Makefile $(INCS) bldday.h ioctl.h
    9194
    9295pci.obj:      pci.c      Makefile $(INCS)
     
    99102
    100103ctxhook.obj:  ctxhook.c  Makefile $(INCS) ata.h atapi.h
     104
     105apm.obj:      apm.c      Makefile $(INCS)
     106
     107ioctl.obj:    ioctl.c    Makefile $(INCS) atapi.h ioctl.h
    101108
    102109###############################################################################
  • trunk/src/os2ahci/ahci.c

    r75 r76  
    591591
    592592  dprintf("resetting port %d.%d\n", ad_no(ai), p);
     593  ddprintf(" PORT_CMD_ISSUE = 0x%lx\n", readl(port_mmio + PORT_CMD_ISSUE));
     594  ddprintf(" PORT_SCR_ACT   = 0x%lx\n", readl(port_mmio + PORT_SCR_ACT));
     595  ddprintf(" PORT_SCR_ERR   = 0x%lx\n", readl(port_mmio + PORT_SCR_ERR));
     596  ddprintf(" PORT_TFDATA    = 0x%lx\n", readl(port_mmio + PORT_TFDATA));
     597  ddprintf(" PORT_IRQ_STAT  = 0x%lx\n", readl(port_mmio + PORT_IRQ_STAT));
     598  ddprintf(" PORT_IRQ_MASK  = 0x%lx\n", readl(port_mmio + PORT_IRQ_MASK));
     599  ddprintf(" HOST_IRQ_STAT  = 0x%lx\n", readl(ai->mmio + HOST_IRQ_STAT));
    593600
    594601  /* stop port engines (we don't care whether there is an error doing so) */
     
    597604  /* clear SError */
    598605  tmp = readl(port_mmio + PORT_SCR_ERR);
    599   ddprintf(" PORT_SCR_ERR  = 0x%lx\n", tmp);
    600606  writel(port_mmio + PORT_SCR_ERR, tmp);
    601607
    602608  /* clear pending port IRQs */
    603609  tmp = readl(port_mmio + PORT_IRQ_STAT);
    604   ddprintf("PORT_IRQ_STAT was 0x%lx\n", tmp);
    605610  if (tmp) {
    606611    writel(port_mmio + PORT_IRQ_STAT, tmp);
    607612  }
    608   ddprintf(" PORT_IRQ_STAT = 0x%lx\n", tmp);
    609   ddprintf(" PORT_IRQ_MASK = 0x%lx\n", readl(port_mmio + PORT_IRQ_MASK));
    610   ddprintf(" HOST_IRQ_STAT = 0x%lx\n", readl(ai->mmio + HOST_IRQ_STAT));
    611613  writel(ai->mmio + HOST_IRQ_STAT, 1UL << p);
    612614
     
    701703                                      PORT_IRQ_UNK_FIS |
    702704                                      PORT_IRQ_SDB_FIS |
     705                                      PORT_IRQ_DMAS_FIS |
     706                                      PORT_IRQ_PIOS_FIS |
    703707                                      PORT_IRQ_D2H_REG_FIS);
    704708  } else {
     
    759763
    760764  /* disable port interrupts */
    761   writel(port_mmio + PORT_IRQ_MASK, PORT_IRQ_TF_ERR);
     765  writel(port_mmio + PORT_IRQ_MASK, 0);
    762766
    763767  /* disable FIS reception */
     
    839843
    840844  return((timeout <= 0) ? -1 : 0);
     845}
     846
     847/******************************************************************************
     848 * Determine whether a port is busy executing commands.
     849 */
     850ahci_port_busy(AD_INFO *ai, int p)
     851{
     852  u8 _far *port_mmio = port_base(ai, p);
     853
     854  return(readl(port_mmio + PORT_SCR_ACT) != 0 ||
     855         readl(port_mmio + PORT_CMD_ISSUE) != 0);
    841856}
    842857
     
    931946        ADD_StartTimerMS(&aws->timer, timeout, (PFN) timeout_callback, iorb, 0);
    932947
    933         /* update IORB */
     948        /* issue command to hardware */
     949        *cmds |= (1UL << port->cmd_slot);
    934950        aws->queued_hw = 1;
    935951        aws->cmd_slot = port->cmd_slot;
    936952
    937         /* issue command to hardware */
    938953        ddprintf("issuing command on slot %d\n", port->cmd_slot);
    939         *cmds |= (1UL << port->cmd_slot);
    940954        if (aws->is_ncq) {
    941955          writel(port_mmio + PORT_SCR_ACT, (1UL << port->cmd_slot));
     
    14231437
    14241438/******************************************************************************
    1425  * Execute ATA command.
     1439 * Execute ATA command. Please note that this is allowed for both ATA and
     1440 * ATAPI devices because ATAPI devices will process some ATA commands as well.
    14261441 */
    14271442void ahci_execute_ata(IORBH _far *iorb)
     
    14331448  dphex(((IORB_ADAPTER_PASSTHRU _far *) iorb)->pControllerCmd,
    14341449        ((IORB_ADAPTER_PASSTHRU _far *) iorb)->ControllerCmdLen,
    1435         "ahci_execute_cdb(%d.%d.%d): ", a, p, d);
    1436 
    1437   if (ad_infos[a].ports[p].devs[d].atapi) {
    1438     iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED);
    1439     iorb_done(iorb);
    1440   } else {
    1441     ahci_exec_iorb(iorb, 0, ata_execute_ata);
    1442   }
     1450        "ahci_execute_ata(%d.%d.%d): ", a, p, d);
     1451
     1452  ahci_exec_iorb(iorb, 0, ata_execute_ata);
    14431453}
    14441454
  • trunk/src/os2ahci/ata.h

    r57 r76  
    424424
    425425/******************************************************************************
    426  * Generic ATA-8 command structure. This is based on ATA-8, i.e. we won't have
    427  * to deal with different command structures depending on whether a device is
    428  * 48-bit capable, etc. because this is handled by the transport (AHCI in our
    429  * case). Unsupported bits have to be cleared to zero, of course (e.g. the
    430  * high 20 bits of the LBA when talking to a device that supports only 28
    431  * bits).
     426 * Generic ATA-8 command structure. This is loosely based on ATA-8, i.e. we
     427 * don't have to deal with shadow registers and map them to the low bytes of
     428 * adjecent words, etc. but there are still some oddities which need to be
     429 * taken into consideration. For example, ATA-8 says LBA-28 sector addresses
     430 * are simply the lower 28 bits in the LBA field. However, the underlying
     431 * transport (SATA in our case) only looks at the three lower bytes of the
     432 * LBA field, much like an IDE device would do. This means that only 3 bytes
     433 * of the LBA field are processed and this yields only 24 bits. The remaining
     434 * 4 bits need to be stored in the "device" register....
     435 *
     436 * Everything else seems to behave normally, as far as this term can be
     437 * applied to IDE/ATA. Further details can be found in section 7.1.5.1 of the
     438 * ATA-8 spec (Inputs for 28-bit Read/Write Commands).
    432439 */
    433440typedef struct {
  • trunk/src/os2ahci/atapi.c

    r75 r76  
    168168   * mechanism:" -- Storage Device Driver Reference, Scatter/Gather Lists
    169169   */
    170   rc = ata_cmd(ad_infos + iorb_unit_adapter(iorb),
    171                iorb_unit_port(iorb),
    172                iorb_unit_device(iorb),
    173                slot, ATA_CMD_PACKET,
     170  rc = ata_cmd(ad_infos + iorb_unit_adapter(iorb), iorb_unit_port(iorb),
     171               iorb_unit_device(iorb), slot, ATA_CMD_PACKET,
    174172               AP_ATAPI_CMD, (void _far *) cdb, cdb_len,
    175173               AP_SGLIST, pt->pSGList, pt->cSGList,
     
    280278    if (ssb->SenseData != NULL) {
    281279      memcpy(ssb->SenseData, psd, max(ssb->ReqSenseLen, ATAPI_SENSE_LEN));
    282       ssb->Flags != STATUS_SENSEDATA_VALID;
     280      ssb->Flags |= STATUS_SENSEDATA_VALID;
    283281    }
     282    iorb->Status |= IORB_STATUSBLOCK_AVAIL;
    284283  }
    285284
     
    333332
    334333/******************************************************************************
    335  * pad atapi commands; AHCI requires ATAPI commands to be either 12 or
     334 * Pad ATAPI commands; AHCI requires ATAPI commands to be either 12 or
    336335 * 16 bytes in length. This func converts commands that have a 12 byte
    337336 * equivalent, and pads the others to 12 bytes.
     
    343342{
    344343  ATAPI_CDB_12 _far *p12;
     344  u32 tmp;
    345345
    346346  if (cmd_in_len == ATAPI_MIN_CDB_LEN || cmd_in_len == ATAPI_MAX_CDB_LEN) {
     
    364364    p12->cmd = 0xa0 | (cmd_in[0] & 0x0f);
    365365    p12->flags = cmd_in[1] & 0xc0; /* 6byte cmds have no flags (FUA etc.) */
    366     SET_CDB_32(p12->lba, (u32) cmd_in[3] | (u32) cmd_in[2] << 8 |
    367                          (u32) (cmd_in[1] & 0x1f) << 16);
    368     SET_CDB_32(p12->trans_len, (u32) cmd_in[4]);
     366    tmp = GET_CDB_24(cmd_in + 1) & 0x1fffffUL;
     367    SET_CDB_32(p12->lba, tmp);
     368    SET_CDB_32(p12->trans_len, cmd_in[4]);
    369369    p12->control = cmd_in[5];
    370370    break;
     
    375375    p12->cmd = 0xa0 | (cmd_in[0] & 0x0f);
    376376    p12->flags = cmd_in[1];
     377    p12->control = cmd_in[9];
    377378    memcpy(p12->lba, cmd_in + 2, 4);
    378     SET_CDB_32(p12->trans_len, (u32) GET_CDB_16(cmd_in + 7));
    379     p12->control = cmd_in[9];
     379    tmp = GET_CDB_16(cmd_in + 7);
     380    SET_CDB_32(p12->trans_len, tmp);
    380381    break;
    381382
  • trunk/src/os2ahci/init.asm

    r74 r76  
    2020                PUBLIC  __U4M                ; 32bit unsigned multiply routine
    2121                PUBLIC  __U4D                ; 32bit unsigned divide routine
    22                 PUBLIC  __I4D                ; 32bit signed multiply routine
     22                PUBLIC  __I4D                ; 32bit signed divide routine
    2323                PUBLIC  _end_of_data         ; end of all data (label)
    2424                PUBLIC  _end_of_code         ; end of all code (label)
  • trunk/src/os2ahci/os2ahci.c

    r75 r76  
    2222#include "os2ahci.h"
    2323#include "bldday.h"
     24
     25#include "ioctl.h"
    2426
    2527/* -------------------------- macros and constants ------------------------- */
     
    7880AD_INFO         ad_infos[MAX_AD];  /* adapter information list */
    7981int             ad_info_cnt;       /* number of entries in ad_infos[] */
     82u16             ad_ignore;         /* bitmap with adapter indexes to ignore */
    8083int             init_complete;     /* if != 0, initialization has completed */
    8184
     
    109112  case CMDShutdown:
    110113    rc = exit_drv(((RPSAVERESTORE _far *) req)->FuncCode);
     114    break;
     115
     116  case CMDGenIOCTL:
     117    rc = gen_ioctl((RP_GENIOCTL _far *) req);
    111118    break;
    112119
     
    174181        break;
    175182
    176       case 'i':
     183      case 'g':
    177184        /* add specfied PCI ID as a supported generic AHCI adapter  */
    178185        drv_parm_int(s, vendor, u16, 16);
     
    193200        /* reset ports during initialization */
    194201        init_reset = 1;
     202        break;
     203
     204      case 'i':
     205        /* ignore current adapter index */
     206        if (adapter_index >= 0) {
     207          ad_ignore |= 1U << adapter_index;
     208        }
    195209        break;
    196210
     
    291305
    292306/******************************************************************************
     307 * Generic IOCTL via character device driver. IOCTLs are used to control the
     308 * driver operation and to execute native ATA and ATAPI (SCSI) commands from
     309 * ring 3 applications.
     310 */
     311USHORT gen_ioctl(RP_GENIOCTL _far *ioctl)
     312{
     313  switch (ioctl->Category) {
     314
     315  case OS2AHCI_IOCTL_CATEGORY:
     316
     317    switch (ioctl->Function) {
     318
     319    case OS2AHCI_IOCTL_GET_DEVLIST:
     320      return(ioctl_get_devlist(ioctl));
     321   
     322    case OS2AHCI_IOCTL_PASSTHROUGH:
     323      return(ioctl_passthrough(ioctl));
     324
     325    }
     326  }
     327  return(STDON | STATUS_ERR_UNKCMD);
     328}
     329
     330/******************************************************************************
    293331 * Device driver exit handler. This handler is called when OS/2 shuts down and
    294  * flushes the write caches of all attached devices.
     332 * flushes the write caches of all attached devices. Since this is effectively
     333 * the same we do when suspending, we'll call out to the corresponding APM
     334 * function.
    295335 *
    296336 * NOTE: Errors are ignored because there's no way we could stop the shutdown
     
    300340USHORT exit_drv(int func)
    301341{
    302   int a;
    303   int p;
    304   int d;
    305 
    306342  dprintf("exit_drv(%d) called\n", func);
    307343
     
    311347  }
    312348
    313   for (a = 0; a < ad_info_cnt; a++) {
    314     AD_INFO *ai = ad_infos + a;
    315 
    316     for (p = 0; p <= ai->port_max; p++) {
    317       for (d = 0; d <= ai->ports[p].dev_max; d++) {
    318         if (ai->ports[p].devs[d].present) {
    319           ahci_flush_cache(ai, p, d);
    320         }
    321       }
    322     }
    323   }
    324 
     349  apm_suspend();
    325350  return(STDON);
    326351}
     
    575600    if (!init_complete) {
    576601      dprintf("leaving initialization mode\n");
    577       spin_lock(drv_lock);
    578602      for (a = 0; a < ad_info_cnt; a++) {
     603        lock_adapter(ad_infos + a);
    579604        ahci_complete_init(ad_infos + a);
    580605      }
    581606      init_complete = 1;
    582       spin_unlock(drv_lock);
     607
     608      /* release all adapters */
     609      for (a = 0; a < ad_info_cnt; a++) {
     610        unlock_adapter(ad_infos + a);
     611      }
     612
     613      /* register APM hook */
     614      apm_init();
    583615    }
    584616    iorb_done(iorb);
     
    941973
    942974/******************************************************************************
    943  * Add an IORB to the specified queue.
     975 * Add an IORB to the specified queue. This function must be called with the
     976 * adapter-level spinlock aquired.
    944977 */
    945978void iorb_queue_add(IORB_QUEUE _far *queue, IORBH _far *iorb)
     
    9941027
    9951028/******************************************************************************
    996  * Remove an IORB from the specified queue.
     1029 * Remove an IORB from the specified queue. This function must be called with
     1030 * the adapter-level spinlock aquired.
    9971031 */
    9981032int iorb_queue_del(IORB_QUEUE _far *queue, IORBH _far *iorb)
     
    10371071{
    10381072  iorb->ErrorCode = error_code;
    1039   iorb->Status = IORB_ERROR;
     1073  iorb->Status |= IORB_ERROR;
    10401074}
    10411075
     
    10781112 * Requeue the specified IORB such that it will be sent downstream for
    10791113 * processing again. This includes freeing all resources currently allocated
    1080  * (timer, buffer, ...) and resetting the flags to 0.
     1114 * (timer, buffer, ...) and resetting the flags to 0. The driver-level
     1115 * spinlock must be aquired when calling this function.
    10811116 *
    10821117 * The following flags are preserved:
     
    10911126  memset(aws, 0x00, sizeof(*aws));
    10921127  aws->no_ncq = no_ncq;
     1128}
     1129
     1130/******************************************************************************
     1131 * Lock the adapter, waiting for availability if necessary. This is expected
     1132 * to be called without the driver-level spinlock aquired.
     1133 */
     1134void lock_adapter(AD_INFO *ai)
     1135{
     1136  spin_lock(drv_lock);
     1137  while (ai->busy) {
     1138    spin_unlock(drv_lock);
     1139    msleep(250);
     1140    spin_lock(drv_lock);
     1141  }
     1142  ai->busy = 1;
     1143  spin_unlock(drv_lock);
     1144}
     1145
     1146/******************************************************************************
     1147 * Unlock adapter (i.e. reset busy flag)
     1148 */
     1149void unlock_adapter(AD_INFO *ai)
     1150{
     1151  ai->busy = 0;
    10931152}
    10941153
  • trunk/src/os2ahci/os2ahci.def

    r75 r76  
    11library os2ahci
    2 Description '$@#thi.guten (www.thiguten.de):1.00.20110216#@OS/2 AHCI Adapter Device Driver'
     2Description '$@#thi.guten (www.thiguten.de):1.00.20110218#@OS/2 AHCI Adapter Device Driver'
    33protmode
    44
  • trunk/src/os2ahci/os2ahci.h

    r75 r76  
    122122/* SMP spinlock compatibility macros for older DDKs using CLI/STI */
    123123#ifndef OS2AHCI_SMP
    124 #define DevHelp_CreateSpinLock(sph)    *(sph) = 0
     124#define DevHelp_CreateSpinLock(p_sph)  *(p_sph) = 0
    125125#define DevHelp_FreeSpinLock(sph)      0
    126126
     
    379379/* os2ahci.c */
    380380extern USHORT  init_drv               (RPINITIN _far *req);
     381extern USHORT  gen_ioctl              (RP_GENIOCTL _far *ioctl);
    381382extern USHORT  exit_drv               (int func);
    382383extern void _cdecl _far _loadds add_entry    (IORBH _far *iorb);
     
    397398extern void    iorb_done              (IORBH _far *iorb);
    398399extern void    iorb_requeue           (IORBH _far *iorb);
     400extern void    lock_adapter           (AD_INFO *ai);
     401extern void    unlock_adapter         (AD_INFO *ai);
    399402extern void _cdecl _far timeout_callback    (ULONG timer_handle, ULONG p1, ULONG p2);
    400403
     
    416419extern int     ahci_stop_fis_rx             (AD_INFO *ai, int p);
    417420extern int     ahci_stop_engine             (AD_INFO *ai, int p);
     421extern int     ahci_port_busy               (AD_INFO *ai, int p);
    418422extern void    ahci_exec_iorb               (IORBH _far *iorb, int ncq_capable,
    419423                                             int (*func)(IORBH _far *, int));
     
    474478extern void _cdecl engine_ctxhook     (ULONG parm);
    475479
     480/* apm.c */
     481extern void        apm_init           (void);
     482extern void        apm_suspend        (void);
     483extern void        apm_resume         (void);
     484
     485/* ioctl.c */
     486extern USHORT      ioctl_get_devlist  (RP_GENIOCTL _far *ioctl);
     487extern USHORT      ioctl_passthrough  (RP_GENIOCTL _far *ioctl);
     488
    476489/* ---------------------------- global variables --------------------------- */
    477490
     
    492505extern AD_INFO       ad_infos[];    /* adapter information list */
    493506extern int           ad_info_cnt;   /* number of entries in ad_infos[] */
     507extern u16           ad_ignore;     /* bitmap with adapters to be ignored */
    494508extern int           init_complete; /* if != 0, initialization has completed */
    495509
  • trunk/src/os2ahci/pci.c

    r48 r76  
    409409  UCHAR index;
    410410  UCHAR rc;
     411  int ad_indx = 0;
    411412  int i;
    412413
     
    460461      if (rc == OH_SUCCESS) {
    461462        /* found a device */
     463        if (ad_ignore & (1U << ad_indx++)) {
     464          /* ignore this adapter */
     465          continue;
     466        }
    462467        add_pci_device(pci_ids + i, &data);
    463468        if (++index > 180) {
  • trunk/src/os2ahci/version.h

    r75 r76  
    66
    77
    8 #define VERSION            102       /* driver version (2 implied decimals) */
     8#define VERSION            103       /* driver version (2 implied decimals) */
    99
    1010/* BLDLEVEL information (in C source modules added via macro
Note: See TracChangeset for help on using the changeset viewer.