Changeset 77 for trunk


Ignore:
Timestamp:
Feb 22, 2011, 2:25:44 AM (14 years ago)
Author:
chris
Message:
  • Further fixes to automatic ATAPI sense handling, now supporting sense buffers larger than 64 bytes if requested by initiator (cdrecord wanted 96 bytes)
  • Separate, and internally handled, spinlock for libc malloc/free calls to reduce chances of memory corruption if somebody forgets to get the driver-level spinlock before calling malloc/free. There was no real problem with that, just some awkward code fragments which look much better now.
  • Link power management implemented
  • More generic support for adapter/port options so all of them can now have a global, adapter or port scope
  • Generic support for inverting driver options (i.e. turn them off with '!')
  • Thorough PCI scan is now the default; the reason it wasn't so far was a delay in Virtualbox but that was never a problem on real hardware
  • SCSI emulation for ATAPI devices; this can be enabled on global, adapter or port scope
Location:
trunk/src/os2ahci
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/os2ahci/ahci.c

    r76 r77  
    413413  int i;
    414414
    415   spin_lock(drv_lock);
    416   id_buf = malloc(ATA_ID_WORDS * sizeof(u16));
    417   spin_unlock(drv_lock);
    418   if (id_buf == NULL) {
     415  if ((id_buf = malloc(ATA_ID_WORDS * sizeof(u16))) == NULL) {
    419416    return(-1);
    420417  }
     
    499496    ahci_restore_bios_config(ai);
    500497  }
    501   spin_lock(drv_lock);
    502498  free(id_buf);
    503   spin_unlock(drv_lock);
    504499  return(0);
    505500}
     
    613608  writel(ai->mmio + HOST_IRQ_STAT, 1UL << p);
    614609
    615   /* set link speed */
    616   tmp = readl(port_mmio + PORT_SCR_CTL) & ~0x000000f0UL;
    617   writel(port_mmio + PORT_SCR_CTL, tmp | (link_speed[ad_no(ai)][p] << 4));
     610  /* set link speed and power management options */
     611  tmp = readl(port_mmio + PORT_SCR_CTL) & ~0x00000ff0UL;
     612  tmp |= ((u32) link_speed[ad_no(ai)][p] & 0x0f) << 4;
     613  tmp |= ((u32) link_power[ad_no(ai)][p] & 0x0f) << 8;
     614  writel(port_mmio + PORT_SCR_CTL, tmp);
    618615
    619616  /* issue COMRESET on the port */
     
    873870  AD_INFO *ai = ad_infos + iorb_unit_adapter(iorb);
    874871  P_INFO *port = ai->ports + iorb_unit_port(iorb);
    875   ULONG timeout = (iorb->Timeout > 0) ? iorb->Timeout * 1000 : DEFAULT_TIMEOUT;
     872  ULONG timeout;
    876873  u8 _far *port_mmio = port_base(ai, iorb_unit_port(iorb));
    877874  u16 cmd_max = ai->cmd_max;
    878875  int i;
     876
     877  /* determine timeout in milliseconds */
     878  switch (iorb->Timeout) {
     879  case 0:
     880    timeout = DEFAULT_TIMEOUT;
     881    break;
     882  case 0xffffffffUL:
     883    timeout = 0xffffffffUL;
     884    break;
     885  default:
     886    timeout = iorb->Timeout * 1000;
     887    break;
     888  }
    879889
    880890  /* Enable AHCI mode; apparently, the AHCI mode may end up becoming
     
    12961306  for (iorb = done_queue.root; iorb != NULL; iorb = next) {
    12971307    next = iorb->pNxtIORB;
    1298     complete_iorb(iorb);
     1308    iorb_complete(iorb);
    12991309  }
    13001310}
     
    15411551
    15421552  /* try to detect virtualbox environment to enable a hack for IRQ routing */
    1543   if (ai == ad_infos && p == 7 &&
    1544       ai->pci->vendor == 0x8086 && ai->pci->device == 0x2829 &&
     1553  if (ai == ad_infos && ai->pci->vendor == 0x8086 && ai->pci->device == 0x2829 &&
    15451554      !memcmp(ata_dev_name(id_buf), "VBOX HARDDISK", 13)) {
    15461555    /* running inside virtualbox */
  • trunk/src/os2ahci/atapi.c

    r76 r77  
    201201  u8 cdb[ATAPI_MIN_CDB_LEN];
    202202  ATAPI_CDB_6 _far *pcdb = (ATAPI_CDB_6 _far *) cdb;
     203  size_t sense_buf_len = ATAPI_SENSE_LEN;
    203204
    204205  if ((iorb->RequestControl & IORB_REQ_STATUSBLOCK) &&
     
    211212                                       (u16) iorb->pStatusBlock);
    212213    if (ssb->Flags & 0x0008U) {
    213       /* set a generic error code and skip automatic sense code handling */
    214214      iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
    215215      return(-1);
    216216    }
     217
     218    /* if the sense buffer requested is larger than our default, adjust
     219     * the length accordingly to satisfy the caller's requirements. */
     220    if (ssb->SenseData != NULL && ssb->ReqSenseLen > sense_buf_len) {
     221      sense_buf_len = ssb->ReqSenseLen;
     222    }
    217223  }
    218224
    219225  /* allocate sense buffer in ADD workspace */
    220   if ((aws->buf = malloc(ATAPI_SENSE_LEN)) == NULL) {
     226  if ((aws->buf = malloc(sense_buf_len)) == NULL) {
    221227    iorb_seterr(iorb, IOERR_CMD_SW_RESOURCE);
    222228    return(-1);
    223229  }
    224   memset(aws->buf, 0x00, ATAPI_SENSE_LEN);
     230  memset(aws->buf, 0x00, sense_buf_len);
    225231
    226232  /* prepare request sense command */
    227233  memset(cdb, 0x00, sizeof(cdb));
    228234  pcdb->cmd = ATAPI_CMD_REQUEST_SENSE;
    229   pcdb->trans_len = (u8) ATAPI_SENSE_LEN;
     235  pcdb->trans_len = (u8) sense_buf_len;
    230236 
    231237  aws->ppfunc = atapi_req_sense_pp;
     
    236242               ATA_CMD_PACKET,
    237243               AP_ATAPI_CMD, (void _far*) cdb, sizeof(cdb),
    238                AP_VADDR, (void _far *) aws->buf, ATAPI_SENSE_LEN,
     244               AP_VADDR, (void _far *) aws->buf, sense_buf_len,
    239245               AP_FEATURES,  ATAPI_FEAT_DMA,
    240246               AP_END);
     
    277283
    278284    if (ssb->SenseData != NULL) {
    279       memcpy(ssb->SenseData, psd, max(ssb->ReqSenseLen, ATAPI_SENSE_LEN));
     285      memcpy(ssb->SenseData, psd, ssb->ReqSenseLen);
    280286      ssb->Flags |= STATUS_SENSEDATA_VALID;
    281287    }
  • trunk/src/os2ahci/ctxhook.c

    r75 r77  
    224224    spin_unlock(drv_lock);
    225225
    226     complete_iorb(iorb);
     226    iorb_complete(iorb);
    227227  }
    228228
     
    371371    spin_unlock(drv_lock);
    372372
    373     iorb->Status = IORB_ERROR;
    374     complete_iorb(iorb);
     373    iorb->Status |= IORB_ERROR;
     374    iorb_complete(iorb);
    375375  }
    376376
  • trunk/src/os2ahci/libc.c

    r71 r77  
    6060
    6161static char  hex_digits[] = "0123456789abcdef";
     62static ULONG mem_lock;
    6263static ULONG com_lock;
    6364
     
    9495
    9596/******************************************************************************
    96  * Initialize COM1 to 115200,n,8,1
     97 * Initialize libc components
     98 */
     99void init_libc(void)
     100{
     101  DevHelp_CreateSpinLock(&mem_lock);
     102  DevHelp_CreateSpinLock(&com_lock);
     103}
     104
     105/******************************************************************************
     106 * Initialize COM port to 115200,n,8,1
    97107 *
    98108 * NOTE: Something is wrong with this code, or the init sequence, but we never
    99109 *       got around to fixing it because it works fine on Virtualbox, and on
    100110 *       physical machines we tend to have the kernel debugger running on the
    101  *       same port simply because serial ports are not that plenty on PCs
    102  *       these days, thus KDB will set port parameters for us. This is going
     111 *       same port, thus KDB will set port parameters for us. This is going
    103112 *       to be fixed eventually...
    104113 */
    105 void init_com1(void)
     114void init_com(void)
    106115{
    107116  int i;
     
    462471 * sense buffers, etc. and should be freed as soon as possible, otherwise
    463472 * we'll quickly run out of memory.
    464  *
    465  * NOTE: This function is not reentrant, thus must be called with the driver-
    466  *       level spinlock held. The main reason for this design is that most
    467  *       functions that need dynamic memory are already holding the spinlock.
    468473 */
    469474void *malloc(size_t len)
     
    472477  u16 i;
    473478  u16 n;
     479
     480  spin_lock(mem_lock);
    474481
    475482  /* find a sequence of free heap units big enough for the requested length */
     
    486493          heap_units[i] = (u8) (n - i);
    487494        }
     495        spin_unlock(mem_lock);
    488496        return(heap_buf + (n - units) * HEAP_UNIT);
    489497      }
     
    498506
    499507  /* out of memory */
     508  spin_unlock(mem_lock);
    500509  dprintf("malloc(%d): out of memory\n", len);
    501510  return(NULL);
     
    524533
    525534  /* clear unit allocation counters in heap_units[] */
     535  spin_lock(mem_lock);
     536
    526537  first_unit = (u16) (p - heap_buf) / HEAP_UNIT;
    527538  units = heap_units[first_unit];
     
    529540    heap_units[i] = 0;
    530541  }
     542
     543  spin_unlock(mem_lock);
    531544}
    532545
  • trunk/src/os2ahci/os2ahci.c

    r76 r77  
    4141  }
    4242
     43/* set two-dimensional array of port options */
     44#define set_port_option(opt, val)                         \
     45  if (adapter_index == -1) {                              \
     46    /* set option for all adapters and ports */           \
     47    memset(opt, val, sizeof(opt));                        \
     48  } else if (port_index == -1) {                          \
     49    /* set option for all ports on current adapter */     \
     50    memset(opt[adapter_index], val, sizeof(*opt));        \
     51  } else {                                                \
     52    /* set option for specific port */                    \
     53    opt[adapter_index][port_index] = val;                 \
     54  }
     55
    4356/* ------------------------ typedefs and structures ------------------------ */
    4457
    4558/* -------------------------- function prototypes -------------------------- */
    4659
    47 void     _cdecl small_code_          (void);
     60void _cdecl  small_code_      (void);
     61
     62static int   add_unit_info    (IORB_CONFIGURATION _far *iorb_conf, int dt_ai,
     63                               int a, int p, int d, int scsi_id);
    4864
    4965/* ------------------------ global/static variables ------------------------ */
    5066
    5167int             debug = 0;         /* if > 0, print debug messages to COM1 */
    52 int             thorough_scan;    /* if != 0, perform thorough PCI scan */
     68int             thorough_scan = 1; /* if != 0, perform thorough PCI scan */
    5369int             init_reset;        /* if != 0, reset ports during init */
    5470
     
    84100
    85101/* apapter/port-specific options saved when parsing the command line */
     102u8              emulate_scsi[MAX_AD][AHCI_MAX_PORTS];
     103u8              disable_ncq[MAX_AD][AHCI_MAX_PORTS];
    86104u8              link_speed[MAX_AD][AHCI_MAX_PORTS];
    87 u8              disable_ncq[MAX_AD][AHCI_MAX_PORTS];
     105u8              link_power[MAX_AD][AHCI_MAX_PORTS];
    88106
    89107static char     init_msg[] = "OS2AHCI driver version %d.%02d\n";
     
    91109static char     eval_msg[] = ANSI_CLR_RED ANSI_CLR_BRIGHT "Evaluation version "
    92110                             "- not licensed for production use.\n" ANSI_RESET;
    93 
    94111
    95112/* ----------------------------- start of code ----------------------------- */
     
    139156  int adapter_index = -1;
    140157  int port_index = -1;
     158  int invert_option;
     159  int optval;
    141160  u16 vendor;
    142161  u16 device;
     
    148167  DevHelp_CreateSpinLock(&drv_lock);
    149168
    150   if (debug) {
    151     /* initialize debug interface (COM1) */
    152     init_com1();
    153   }
     169  /* initialize libc code */
     170  init_libc();
    154171
    155172  /* print initialization message */
     
    167184
    168185  for (s = cmd_line; *s != 0; s++) {
    169     if (*s == '/' && s[1] != '\0') {
     186    if (*s == '/') {
     187      if ((invert_option = (s[1] == '!')) != 0) {
     188        s++;
     189      }
    170190      s++;
    171       switch(tolower(*s)) {
     191      switch (tolower(*s)) {
     192
     193      case '\0':
     194        /* end of command line; can only happen if command line is incorrect */
     195        cprintf("incomplete command line option\n");
     196        goto init_fail;
    172197
    173198      case 'c':
     
    178203      case 'd':
    179204        /* increase debug level */
    180         debug++;
     205        if (debug++ == 0) {
     206          init_com();
     207        }
    181208        break;
    182209
     
    194221      case 't':
    195222        /* perform thorough PCI scan (i.e. look for individual supported PCI IDs) */
    196         thorough_scan = 1;
     223        thorough_scan = !invert_option;
    197224        break;
    198225
     
    200227        /* reset ports during initialization */
    201228        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         }
    209229        break;
    210230
     
    227247        break;
    228248
     249      case 'i':
     250        /* ignore current adapter index */
     251        if (adapter_index >= 0) {
     252          ad_ignore |= 1U << adapter_index;
     253        }
     254        break;
     255
    229256      case 's':
    230         /* set link speed of current port on current adapter */
    231         drv_parm_int(s, link_speed[adapter_index][port_index], u8, 10);
    232         init_reset = 1;
     257        /* enable SCSI emulation for ATAPI devices */
     258        set_port_option(emulate_scsi, !invert_option);
    233259        break;
    234260
    235261      case 'n':
    236262        /* disable NCQ */
    237         if (adapter_index == -1) {
    238           /* disable NCQ on all adapters and ports */
    239           memset(disable_ncq, 0x01, sizeof(disable_ncq));
    240         } else if (port_index == -1) {
    241           /* disable NCQ on all ports of this adapter */
    242           memset(disable_ncq[adapter_index], 0x01, sizeof(*disable_ncq));
    243         } else {
    244           /* disable NCQ for this adapter and port */
    245           disable_ncq[adapter_index][port_index] = 1;
    246         }
     263        set_port_option(disable_ncq, !invert_option);
     264        break;
     265
     266      case 'l':
     267        /* set link speed or power savings */
     268        s++;
     269        switch (tolower(*s)) {
     270        case 's':
     271          /* set link speed */
     272          drv_parm_int(s, optval, int, 10);
     273          set_port_option(link_speed, optval);
     274          break;
     275        case 'p':
     276          /* set power management */
     277          drv_parm_int(s, optval, int, 10);
     278          set_port_option(link_power, optval);
     279          break;
     280        default:
     281          cprintf("invalid link parameter (%c)\n", *s);
     282          goto init_fail;
     283        }
     284        /* need to reset the port in order to establish link settings */
     285        init_reset = 1;
    247286        break;
    248287
     
    402441        iorb->Status = IORB_ERROR;
    403442        iorb->ErrorCode = IOERR_CMD_SYNTAX;
    404         complete_iorb(iorb);
     443        iorb_complete(iorb);
    405444        continue;
    406445      }
     
    744783 * Scan all ports for AHCI devices and construct a DASD device table.
    745784 *
    746  * NOTE: This function may be called multiple times. Only the first invocation
    747  *       will actually scan for devices; all subsequent calls will merely
    748  *       return the results of the initial scan, potentially augmented by
    749  *       modified unit infos after IOCC_CONFIGURATION/IOCM_CHANGE_UNITINFO
    750  *       requests.
     785 * NOTES: This function may be called multiple times. Only the first
     786 *        invocation will actually scan for devices; all subsequent calls will
     787 *        merely return the results of the initial scan, potentially augmented
     788 *        by modified unit infos after IOCC_CONFIGURATION/IOCM_CHANGE_UNITINFO
     789 *        requests.
     790 *
     791 *        In order to support applications that can't deal with ATAPI devies
     792 *        (i.e. need a SCSI adapter) os2ahci will optionally report ATAPI
     793 *        dvices as SCSI devices. The corresponding SCSI adapter doesn't
     794 *        really  exist and is only reported here for the IOCM_GET_DEVICETABLE
     795 *        request. The units attached to this adapter will use the real HW
     796 *        unit IDs, thus we'll never receive a command specific to the
     797 *        emulated SCSI adapter and won't need to set up any sort of entity
     798 *        for it; the only purpose of the emulated SCSI adapter is to pass the
     799 *        bus type "AI_DEVBUS_SCSI_2" upstream, and the emulated units, of
     800 *        course. The emulated SCSI target IDs are allocated as follows:
     801 *
     802 *         0     the virtual adapter
     803 *         1..n  emulated devices; SCSI target ID increments sequentially
    751804 */
    752805void iocm_device_table(IORBH _far *iorb)
     
    755808  DEVICETABLE _far *dt;
    756809  char _far *pos;
     810  int scsi_units = 0;
     811  int scsi_id = 1;
    757812  int rc;
     813  int dta;
    758814  int a;
    759815  int p;
     
    769825  dt->ADDLevelMinor = ADD_LEVEL_MINOR;
    770826  dt->ADDHandle     = add_handle;
    771   dt->TotalAdapters = ad_info_cnt;
    772 
    773   /* Initial position of dynamic portion of device table (i.e. behind the
    774    * array of ADAPTERINFO pointers, pAdapter, in the device table)
    775    */
    776   pos = (char _far *) (dt->pAdapter + ad_info_cnt);
    777 
    778   for (a = 0; a < ad_info_cnt; a++) {
     827  dt->TotalAdapters = ad_info_cnt + 1;
     828   
     829  /* set start of adapter and device information tables */
     830  pos = (char _far *) (dt->pAdapter + dt->TotalAdapters);
     831
     832  /* go through all adapters, including the virtual SCSI adapter */
     833  for (dta = 0; dta < dt->TotalAdapters; dta++) {
    779834    ADAPTERINFO _far *ptr = (ADAPTERINFO _far *) pos;
    780     AD_INFO *ad_info = ad_infos + a;
    781     int units = 0;
    782835
    783836    /* sanity check for sufficient space in device table */
     
    788841    }
    789842
    790     /* set ADAPTERINFO offset in device table */
    791     dt->pAdapter[a] = (ADAPTERINFO _near *) ((u32) ptr & 0xffff);
    792 
    793     /* fill in adapter information structure in device table */
     843    dt->pAdapter[dta] = (ADAPTERINFO _near *) ((u32) ptr & 0xffff);
    794844    memset(ptr, 0x00, sizeof(*ptr));
    795     sprintf(ptr->AdapterName, "AHCI_%d", a);
    796     ptr->AdapterDevBus   = AI_DEVBUS_ST506 | AI_DEVBUS_32BIT;
     845
    797846    ptr->AdapterIOAccess = AI_IOACCESS_BUS_MASTER;
    798847    ptr->AdapterHostBus  = AI_HOSTBUS_OTHER | AI_BUSWIDTH_32BIT;
    799848    ptr->AdapterFlags    = AF_16M | AF_HW_SCATGAT;
    800 
    801     /* AHCI limits S/G elements to 22 bits, thus we'll report only half of
    802      * our S/G list buffers to reduce complexity. The command preparation code
    803      * will always try to map as many S/G elements as possible so the physical
    804      * S/G list capacity is not really wasted except in rare conditions where
    805      * we need to split commands with long S/G lists without any suitable split
    806      * points except those at the reported MaxHWSGList.
    807      */
    808     ptr->MaxHWSGList     = AHCI_MAX_SG / 2;
    809 
    810     if (!ad_info->port_scan_done) {
    811       /* First call; need to scan AHCI hardware for devices. Since this might
    812        * be a lengthy operation, especially when init_reset is set, we'll mark
    813        * the adapter as busy (new IORBs will only be queued but not executed)
    814        * and release the spinlock while scanning the ports so interrupts will
    815        * be processed.
    816        */
    817       if (ad_info->busy) {
    818         dprintf("error: port scan requested while adapter was busy\n");
    819         iorb_seterr(iorb, IOERR_CMD_SW_RESOURCE);
    820         goto iocm_device_table_done;
     849    ptr->MaxHWSGList     = AHCI_MAX_SG / 2;   /* AHCI S/G elements are 22 bits */
     850
     851    if (dta < ad_info_cnt) {
     852      /* this is a physical AHCI adapter */
     853      AD_INFO *ad_info = ad_infos + dta;
     854
     855      ptr->AdapterDevBus = AI_DEVBUS_ST506 | AI_DEVBUS_32BIT;
     856      sprintf(ptr->AdapterName, "AHCI_%d", dta);
     857
     858      if (!ad_info->port_scan_done) {
     859        /* first call; need to scan AHCI hardware for devices */
     860        if (ad_info->busy) {
     861          dprintf("error: port scan requested while adapter was busy\n");
     862          iorb_seterr(iorb, IOERR_CMD_SW_RESOURCE);
     863          goto iocm_device_table_done;
     864        }
     865        ad_info->busy = 1;
     866        spin_unlock(drv_lock);
     867        rc = ahci_scan_ports(ad_info);
     868        spin_lock(drv_lock);
     869        ad_info->busy = 0;
     870
     871        if (rc != 0) {
     872          dprintf("error: port scan failed on adapter #%d\n", dta);
     873          iorb_seterr(iorb, IOERR_CMD_SW_RESOURCE);
     874          goto iocm_device_table_done;
     875        }
     876        ad_info->port_scan_done = 1;
    821877      }
    822       ad_info->busy = 1;
    823       spin_unlock(drv_lock);
    824       rc = ahci_scan_ports(ad_info);
    825       spin_lock(drv_lock);
    826       ad_info->busy = 0;
    827 
    828       if (rc != 0) {
    829         dprintf("error: port scan failed on adapter #%d\n", a);
    830         iorb_seterr(iorb, IOERR_CMD_SW_RESOURCE);
    831         goto iocm_device_table_done;
    832       }
    833       ad_info->port_scan_done = 1;
    834     }
    835 
    836     /* insert devices (units) into the device table */
    837     for (p = 0; p <= ad_info->port_max; p++) {
    838       for (d = 0; d <= ad_info->ports[p].dev_max; d++) {
    839         if (ad_info->ports[p].devs[d].present) {
    840           UNITINFO _far *ui = ptr->UnitInfo + units;
    841 
    842           /* sanity check for sufficient space in device table */
    843           if ((u32) (ui + 1) - (u32) dt > iorb_conf->DeviceTableLen) {
    844             dprintf("error: device table provided by DASD too small\n");
    845             iorb_seterr(iorb, IOERR_CMD_SW_RESOURCE);
    846             goto iocm_device_table_done;
     878
     879      /* insert physical (i.e. AHCI) devices into the device table */
     880      for (p = 0; p <= ad_info->port_max; p++) {
     881        for (d = 0; d <= ad_info->ports[p].dev_max; d++) {
     882          if (ad_info->ports[p].devs[d].present) {
     883            if (ad_info->ports[p].devs[d].atapi && emulate_scsi[dta][p]) {
     884              /* only report this unit as SCSI unit */
     885              scsi_units++;
     886              continue;
     887            }
     888            if (add_unit_info(iorb_conf, dta, dta, p, d, 0)) {
     889              goto iocm_device_table_done;
     890            }
    847891          }
    848 
    849           if (ad_info->ports[p].devs[d].unit_info == NULL) {
    850             /* provide initial information about this device (unit) */
    851             memset(ui, 0x00, sizeof(*ui));
    852             ui->AdapterIndex = a;
    853             ui->UnitIndex    = units;
    854             ui->UnitHandle   = iorb_unit(a, p, d);
    855             ui->UnitType     = ad_info->ports[p].devs[d].dev_type;
    856             ui->QueuingCount = ad_info->ports[p].devs[d].ncq_max;;
    857             if (ad_info->ports[p].devs[d].removable) {
    858               ui->UnitFlags |= UF_REMOVABLE;
    859             }
    860           } else {
    861             /* copy updated device (unit) information (IOCM_CHANGE_UNITINFO) */
    862             memcpy(ui, ad_info->ports[p].devs[d].unit_info, sizeof(*ui));
    863           }
    864           units++;
    865892        }
    866893      }
    867     }
    868 
    869     /* set total device (unit) count for this adapter */
    870     ptr->AdapterUnits = units;
     894
     895    } else {
     896      /* this is the virtual SCSI adapter */
     897      if (scsi_units == 0) {
     898        /* not a single unit to be emulated via SCSI */
     899        dt->TotalAdapters--;
     900        break;
     901      }
     902
     903      /* set adapter name and bus type to mimic a SCSI controller */
     904      ptr->AdapterDevBus = AI_DEVBUS_SCSI_2 | AI_DEVBUS_16BIT;
     905      sprintf(ptr->AdapterName, "AHCI_SCSI_0");
     906
     907      /* add all ATAPI units to be emulated by this virtual adaper */
     908      for (a = 0; a < ad_info_cnt; a++) {
     909        AD_INFO *ad_info = ad_infos + a;
     910
     911        for (p = 0; p <= ad_info->port_max; p++) {
     912          for (d = 0; d <= ad_info->ports[p].dev_max; d++) {
     913            if (ad_info->ports[p].devs[d].present &&
     914                ad_info->ports[p].devs[d].atapi &&
     915                emulate_scsi[a][p]) {
     916              if (add_unit_info(iorb_conf, dta, a, p, d, scsi_id++)) {
     917                goto iocm_device_table_done;
     918              }
     919            }
     920          }
     921        }
     922      }
     923    }
    871924
    872925    /* calculate offset for next adapter */
    873     pos = (char _far *) (ptr->UnitInfo + units);
     926    pos = (char _far *) (ptr->UnitInfo + ptr->AdapterUnits);
    874927  }
    875928
     
    10881141 *        Due to this logic, this function is only good for simple task-time
    10891142 *        completions. Functions working on lists of IORBs (such as interrupt
    1090  *        handlers or context hooks) should implement their own logic. See
    1091  *        abort_ctxhook() for an example.
     1143 *        handlers or context hooks) should call iorb_complete() directly and
     1144 *        implement their own logic for removing the IORB from the port queue.
     1145 *        See abort_ctxhook() for an example.
    10921146 */
    10931147void iorb_done(IORBH _far *iorb)
     
    11061160  spin_unlock(drv_lock);
    11071161
    1108   complete_iorb(iorb);
     1162  iorb_complete(iorb);
     1163}
     1164
     1165/******************************************************************************
     1166 * Complete an IORB. It should be called without the adapter-level spinlock
     1167 * to allow the IORB completion routine to perform whatever processing it
     1168 * requires. This implies that the IORB should no longer be in any global
     1169 * queue because the IORB completion routine may well reuse the IORB and send
     1170 * the next request to us before even returning from this function.
     1171 */
     1172void iorb_complete(IORBH _far *iorb)
     1173{
     1174  iorb->Status |= IORB_DONE;
     1175
     1176  dprintf("IORB %Fp complete (status = 0x%04x, error = 0x%04x)\n",
     1177          iorb, iorb->Status, iorb->ErrorCode);
     1178
     1179  if (iorb->RequestControl & IORB_ASYNC_POST) {
     1180    iorb->NotifyAddress(iorb);
     1181  }
    11091182}
    11101183
     
    11261199  memset(aws, 0x00, sizeof(*aws));
    11271200  aws->no_ncq = no_ncq;
     1201}
     1202
     1203/******************************************************************************
     1204 * Free resources in ADD workspace (timer, buffer, ...). This function should
     1205 * be called with the spinlock held to prevent race conditions.
     1206 */
     1207void aws_free(ADD_WORKSPACE _far *aws)
     1208{
     1209  if (aws->timer != 0) {
     1210    ADD_CancelTimer(aws->timer);
     1211    aws->timer = 0;
     1212  }
     1213
     1214  if (aws->buf != NULL) {
     1215    free(aws->buf);
     1216    aws->buf = NULL;
     1217  }
    11281218}
    11291219
     
    12011291{
    12021292}
     1293
     1294/******************************************************************************
     1295 * Add unit info to ADAPTERINFO array (IOCC_GET_DEVICE_TABLE requests). The
     1296 * adapter info array in the device table, dt->pAdapter[], is expected to be
     1297 * initialized for the specified index (dt_ai).
     1298 *
     1299 * Please note that the device table adapter index, dta, is not always equal
     1300 * to the physical adapter index, a: if SCSI emulation has been activated, the
     1301 * last reported adapter is a virtual SCSI adapter and the physical adapter
     1302 * indexes for those units are, of course, different from the device table
     1303 * index of the virtual SCSI adapter.
     1304 */
     1305static int add_unit_info(IORB_CONFIGURATION _far *iorb_conf, int dta,
     1306                         int a, int p, int d, int scsi_id)
     1307{
     1308  DEVICETABLE _far *dt = iorb_conf->pDeviceTable;
     1309  ADAPTERINFO _far *ptr = (ADAPTERINFO _far *) (((u32) dt & 0xffff0000U) +
     1310                                                 (u16) dt->pAdapter[dta]);
     1311  UNITINFO _far *ui = ptr->UnitInfo + ptr->AdapterUnits;
     1312  AD_INFO *ai = ad_infos + a;
     1313
     1314  if ((u32) (ui + 1) - (u32) dt > iorb_conf->DeviceTableLen) {
     1315    dprintf("error: device table provided by DASD too small\n");
     1316    iorb_seterr(&iorb_conf->iorbh, IOERR_CMD_SW_RESOURCE);
     1317    return(-1);
     1318  }
     1319
     1320  if (ai->ports[p].devs[d].unit_info == NULL) {
     1321    /* provide original information about this device (unit) */
     1322    memset(ui, 0x00, sizeof(*ui));
     1323    ui->AdapterIndex = dta;                 /* device table adapter index */
     1324    ui->UnitHandle   = iorb_unit(a, p, d);  /* physical adapter index */
     1325    ui->UnitIndex    = ptr->AdapterUnits;
     1326    ui->UnitType     = ai->ports[p].devs[d].dev_type;
     1327    ui->QueuingCount = ai->ports[p].devs[d].ncq_max;;
     1328    if (ai->ports[p].devs[d].removable) {
     1329      ui->UnitFlags |= UF_REMOVABLE;
     1330    }
     1331    if (scsi_id > 0) {
     1332      /* set fake SCSI ID for this unit */
     1333      ui->UnitSCSITargetID = scsi_id;
     1334    }
     1335  } else {
     1336    /* copy updated device (unit) information (IOCM_CHANGE_UNITINFO) */
     1337    memcpy(ui, ai->ports[p].devs[d].unit_info, sizeof(*ui));
     1338  }
     1339
     1340  ptr->AdapterUnits++;
     1341  return(0);
     1342}
     1343
  • trunk/src/os2ahci/os2ahci.def

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

    r76 r77  
    115115/* ctype macros */
    116116#define isupper(ch)           ((ch) >= 'A' && (ch) <= 'Z')
    117 #define tolower(ch)           (isupper(ch) ? (ch) - ('a' - 'A') : (ch))
     117#define tolower(ch)           (isupper(ch) ? (ch) + ('a' - 'A') : (ch))
    118118
    119119/* stddef macros */
     
    192192#define add_workspace(iorb)     ((ADD_WORKSPACE _far *) &(iorb)->ADDWorkSpace)
    193193
    194 /* free resources in ADD workspace (timer, buffer, ...) */
    195 #define aws_free(aws)           if ((aws)->timer != 0) {               \
    196                                   ADD_CancelTimer((aws)->timer);       \
    197                                   (aws)->timer = 0;                    \
    198                                 }                                      \
    199                                 if ((aws)->buf != NULL) {              \
    200                                   free((aws)->buf);                    \
    201                                   (aws)->buf = NULL;                   \
    202                                 }
    203 
    204 /* complete IORB */
    205 #define complete_iorb(iorb)   (iorb)->Status |= IORB_DONE;                    \
    206                               dprintf("IORB %Fp complete "                    \
    207                                       "(status = 0x%04x, error = 0x%04x)\n",  \
    208                                       (iorb), (iorb)->Status,                 \
    209                                       (iorb)->ErrorCode);                     \
    210                               if ((iorb)->RequestControl & IORB_ASYNC_POST) { \
    211                                 (iorb)->NotifyAddress(iorb);                  \
    212                               }
    213194
    214195
     
    264245#define ANSI_CLR_WHITE  "\x1b[37m"
    265246#define ANSI_RESET      "\x1b[0m"
    266 
    267247
    268248/* ------------------------ typedefs and structures ------------------------ */
     
    397377extern void    iorb_seterr            (IORBH _far *iorb, USHORT error_code);
    398378extern void    iorb_done              (IORBH _far *iorb);
     379extern void    iorb_complete          (IORBH _far *iorb);
    399380extern void    iorb_requeue           (IORBH _far *iorb);
     381extern void    aws_free               (ADD_WORKSPACE _far *aws);
    400382extern void    lock_adapter           (AD_INFO *ai);
    401383extern void    unlock_adapter         (AD_INFO *ai);
     
    443425
    444426/* libc.c */
    445 extern void        init_com1     (void);
     427extern void        init_libc     (void);
     428extern void        init_com      (void);
    446429extern int         vsprintf      (char _far *buf, const char *fmt, va_list va);
    447430extern int         sprintf       (char _far *buf, const char *fmt, ...);
     
    523506
    524507/* apapter/port-specific options saved when parsing the command line */
     508extern u8            emulate_scsi[MAX_AD][AHCI_MAX_PORTS];
     509extern u8            disable_ncq[MAX_AD][AHCI_MAX_PORTS];
    525510extern u8            link_speed[MAX_AD][AHCI_MAX_PORTS];
    526 extern u8            disable_ncq[MAX_AD][AHCI_MAX_PORTS];
    527 
     511extern u8            link_power[MAX_AD][AHCI_MAX_PORTS];
     512
  • trunk/src/os2ahci/pci.c

    r76 r77  
    620620   *       resource is added to the corresponding rc_list.hResource[] slot.
    621621   *       rc_list is used further down to associate resources to adapters
    622    *       whe the adapter itself is registered with the OS/2 resource manager.
     622   *       when the adapter itself is registered with the OS/2 resource
     623   *       manager.
    623624   */
    624625  ad_info = ad_infos + ad_info_cnt;
  • trunk/src/os2ahci/version.h

    r76 r77  
    66
    77
    8 #define VERSION            103       /* driver version (2 implied decimals) */
     8#define VERSION            104       /* 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.