I answered this here but only for 'Disk Drive' type devices, so I have updated the filters to include CD ROM devices like so:
# query for wmi objects
$drivers = Get-CimInstance win32_pnpsignedDriver -filter 'DeviceName="Disk drive" OR DeviceName="CD-ROM Drive"'
$disks = Get-CimInstance Win32_PnPEntity | ? {$_.service -in 'disk','cdrom' -and $_.name -ne 'Xvd'} # Xvd is an xbox/windows-store-related device
# Iterate through disks
$result = foreach ($disk in $disks) {
# disk controllers are usually either IDE (IDE/SATA) or SCSI (NVME/M.2/virtual)
$controller = Get-CimInstance -query "ASSOCIATORS OF {Win32_PnPEntity.DeviceID='$($disk.DeviceID)'}" |
Where {$_.CreationClassName -in 'Win32_IDEController','Win32_SCSIController'}
# the driver class lists drive location
$driver = $drivers | where DeviceID -eq $disk.PNPDeviceID
# combine data for result
$disk | select Name,
@{l='location';e={$driver.Location}},
@{l='controllerName';e={$controller.Name}}
}
$result
On my virtual machine, this outputs the list of hard drive and cd rom devices, and where they are plugged in:
Name location controllerName
---- -------- --------------
NECVMWar VMware SATA CD00 Bus Number 0, Target Id 0, LUN 0 Standard SATA ...
VMware Virtual disk SCSI Disk Device Bus Number 0, Target Id 0, LUN 0 LSI Adapter, S...
VMware Virtual disk SCSI Disk Device Bus Number 0, Target Id 1, LUN 0 LSI Adapter, S...
Note: Don't assume how many ports there are based on the location numbers
There is no easy way to tell which/how many ports are unused - Windows just does not track them. The best way to get that information is probably going to be looking up your motherboard specs online.