2 * Copyright (C) 2012, The AROS Development Team. All rights reserved.
3 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
5 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
8 #include <aros/debug.h>
9 #include <aros/atomic.h>
11 #include <proto/exec.h>
12 #include <proto/expansion.h>
13 #include <proto/dos.h>
15 #include <dos/filehandler.h>
17 #include <devices/trackdisk.h>
18 #include <devices/scsidisk.h>
20 #include <scsi/commands.h>
21 #include <scsi/values.h>
24 #include "ahci_scsi.h"
27 #include LC_LIBDEFS_FILE
30 * Execute a SCSI TEST UNIT READY every 250ms, to see
31 * if the medium has changed.
33 static void ahci_PortMonitor(struct Task
*parent
, struct Device
*device
, struct cam_sim
*unit
)
36 struct IORequest
*tmr
;
38 D(bug("%s %d: Monitor Start\n", ((struct Node
*)device
)->ln_Name
, unit
->sim_Unit
));
39 AROS_ATOMIC_INC(unit
->sim_UseCount
);
40 Signal(parent
, SIGBREAKF_CTRL_C
);
42 tmr
= ahci_OpenTimer();
46 if ((mp
= CreateMsgPort())) {
48 if ((io
= CreateIORequest(mp
, sizeof(struct IOStdReq
)))) {
49 BOOL media_present
= FALSE
;
51 struct scsi_generic test_unit_ready
= { .opcode
= SCSI_TEST_UNIT_READY
, };
52 struct scsi_sense_data sense
= {};
53 struct SCSICmd scsi
= {};
55 io
->io_Device
= device
;
56 io
->io_Unit
= (struct Unit
*)unit
;
58 D(bug("%s %d: Monitoring\n", ((struct Node
*)device
)->ln_Name
, unit
->sim_Unit
));
62 io
->io_Command
= HD_SCSICMD
;
65 IOStdReq(io
)->io_Data
= &scsi
;
66 IOStdReq(io
)->io_Length
= sizeof(scsi
);
67 IOStdReq(io
)->io_Actual
= 0;
68 scsi
.scsi_Command
= (UBYTE
*)&test_unit_ready
;
69 scsi
.scsi_CmdLength
= sizeof(test_unit_ready
);
72 scsi
.scsi_Flags
= SCSIF_AUTOSENSE
;
73 scsi
.scsi_SenseData
= (UBYTE
*)&sense
;
74 scsi
.scsi_SenseLength
= sizeof(sense
);
75 scsi
.scsi_SenseActual
= 0;
79 is_present
= (io
->io_Error
== 0) && (scsi
.scsi_Status
== SCSI_GOOD
);
80 // TODO: Check sense for additional information
82 ObtainSemaphore(&unit
->sim_Lock
);
84 unit
->sim_Flags
|= SIMF_MediaPresent
;
86 unit
->sim_Flags
&= ~SIMF_MediaPresent
;
87 if (is_present
!= media_present
)
88 unit
->sim_ChangeNum
++;
89 ReleaseSemaphore(&unit
->sim_Lock
);
91 if (is_present
!= media_present
) {
92 struct IORequest
*msg
;
94 D(bug("%s: Media change detected on ahci.device %d (%s => %s)\n", __func__
, unit
->sim_Unit
, media_present
? "TRUE" : "FALSE", is_present
? "TRUE" : "FALSE"));
97 ForeachNode((struct Node
*)&unit
->sim_IOs
, msg
) {
98 D(bug("%s %d: io_Command = 0x%04x\n", ((struct Node
*)device
)->ln_Name
, unit
->sim_Unit
, msg
->io_Command
));
99 if (msg
->io_Command
== TD_ADDCHANGEINT
) {
100 D(bug("%s %d: Interrupt = 0x%p\n", ((struct Node
*)device
)->ln_Name
, unit
->sim_Unit
, IOStdReq(msg
)->io_Data
));
101 Cause((struct Interrupt
*)IOStdReq(msg
)->io_Data
);
106 media_present
= is_present
;
108 /* Wait 1s to the next scan */
109 } while ((ahci_WaitTO(tmr
, 1, 0, SIGF_DOS
) & SIGF_DOS
) == 0);
115 AROS_ATOMIC_DEC(unit
->sim_UseCount
);
116 D(bug("%s %d: Monitor End\n", ((struct Node
*)device
)->ln_Name
, unit
->sim_Unit
));
119 static int ahci_RegisterPort(struct ahci_port
*ap
)
121 struct AHCIBase
*AHCIBase
= ap
->ap_sc
->sc_dev
->dev_AHCIBase
;
122 struct cam_sim
*unit
;
125 unit
= AllocPooled(AHCIBase
->ahci_MemPool
, sizeof(*unit
));
131 unit
->sim_Unit
= ap
->ap_sc
->sc_dev
->dev_HostID
* 32 + ap
->ap_num
;
132 InitSemaphore(&unit
->sim_Lock
);
133 NEWLIST(&unit
->sim_IOs
);
135 AddTail((struct List
*)&AHCIBase
->ahci_Units
, (struct Node
*)unit
);
137 /* Now that this device is in the unit list, start the disk change monitor */
138 snprintf(name
, sizeof(name
), "ahci.device %d [media]", unit
->sim_Unit
);
139 unit
->sim_Monitor
= NewCreateTask(TASKTAG_NAME
, name
,
140 TASKTAG_PC
, ahci_PortMonitor
,
141 TASKTAG_ARG1
, FindTask(NULL
),
142 TASKTAG_ARG2
, AHCIBase
,
146 Wait(SIGBREAKF_CTRL_C
);
151 static int ahci_UnregisterPort(struct ahci_port
*ap
)
153 struct ahci_softc
*sc
= ap
->ap_sc
;
154 struct AHCIBase
*AHCIBase
;
155 struct cam_sim
*unit
= ap
->ap_sim
;
157 D(bug("ahci_UnregisterPort: %p\n", ap
));
160 D(bug("No softc?\n"));
164 AHCIBase
= sc
->sc_dev
->dev_AHCIBase
;
166 /* Stop the monitor, and wait for IOs to drain,
167 * and users to CloseDevice() the unit.
169 if (unit
->sim_Monitor
)
170 Signal(unit
->sim_Monitor
, SIGF_DOS
);
171 ObtainSemaphore(&unit
->sim_Lock
);
172 while (unit
->sim_UseCount
) {
173 ReleaseSemaphore(&unit
->sim_Lock
);
175 ObtainSemaphore(&unit
->sim_Lock
);
177 ReleaseSemaphore(&unit
->sim_Lock
);
179 /* Remove from the unit list */
181 Remove((struct Node
*)unit
);
184 FreePooled(AHCIBase
->ahci_MemPool
, unit
, sizeof(*unit
));
189 /* Add a bootnode using expansion.library,
190 * but only when dos.library has not yet been initialized.
191 * This way, we get BootNodes if ahci.device is linked in,
192 * but don't if ahci.device is loaded after booting.
194 static BOOL
ahci_RegisterVolume(struct ahci_port
*ap
, struct ata_port
*at
)
196 struct ExpansionBase
*ExpansionBase
;
198 struct DeviceNode
*devnode
;
199 TEXT dosdevname
[4] = "HA0";
200 const ULONG DOS_ID
= AROS_MAKE_ID('D','O','S','\001');
201 const ULONG CDROM_ID
= AROS_MAKE_ID('C','D','V','D');
202 ULONG unit
= device_get_unit(ap
->ap_sc
->sc_dev
) * 32 + ap
->ap_num
;
204 D(bug("%s: ap = %p, at = %p, unit = %d\n", __func__
, ap
, at
, ap
->ap_sim
? ap
->ap_sim
->sim_Unit
: -1));
206 /* See if dos.library has run */
208 dos_loaded
= (FindName (&SysBase
->LibList
, "dos.library") != NULL
);
212 D(bug("%s: refused to register as boot volume - dos.library already loaded\n", __func__
));
216 if (at
== NULL
|| ap
->ap_type
== ATA_PORT_T_NONE
)
219 /* This should be dealt with using some sort of volume manager or such. */
222 case ATA_PORT_T_DISK
:
224 case ATA_PORT_T_ATAPI
:
228 D(bug("[AHCI>>]:-ahci_RegisterVolume called on unknown devicetype\n"));
232 ExpansionBase
= (struct ExpansionBase
*)OpenLibrary("expansion.library",
237 IPTR pp
[4 + DE_BOOTBLOCKS
+ 1];
240 dosdevname
[2] += ap
->ap_num
;
242 dosdevname
[2] = 'A' + (ap
->ap_num
- 10);
244 pp
[0] = (IPTR
)dosdevname
;
245 pp
[1] = (IPTR
)MOD_NAME_STRING
;
247 pp
[DE_TABLESIZE
+ 4] = DE_BOOTBLOCKS
;
248 pp
[DE_SIZEBLOCK
+ 4] = at
->at_identify
.sector_size
;
249 pp
[DE_NUMHEADS
+ 4] = at
->at_identify
.nheads
;
250 pp
[DE_SECSPERBLOCK
+ 4] = 1;
251 pp
[DE_BLKSPERTRACK
+ 4] = at
->at_identify
.nsectors
;
252 pp
[DE_RESERVEDBLKS
+ 4] = 2;
253 pp
[DE_LOWCYL
+ 4] = 0;
254 pp
[DE_HIGHCYL
+ 4] = (ap
->ap_type
== ATA_PORT_T_DISK
) ? (at
->at_identify
.ncyls
-1) : 0;
255 pp
[DE_NUMBUFFERS
+ 4] = 10;
256 pp
[DE_BUFMEMTYPE
+ 4] = MEMF_PUBLIC
;
257 pp
[DE_MAXTRANSFER
+ 4] = 0x00200000;
258 pp
[DE_MASK
+ 4] = ~3;
259 pp
[DE_BOOTPRI
+ 4] = (ap
->ap_type
== ATA_PORT_T_DISK
) ? 0 : 10;
260 pp
[DE_DOSTYPE
+ 4] = (ap
->ap_type
== ATA_PORT_T_DISK
) ? DOS_ID
: CDROM_ID
;
262 pp
[DE_CONTROL
+ 4] = 0;
263 pp
[DE_BOOTBLOCKS
+ 4] = 2;
265 devnode
= MakeDosNode(pp
);
268 D(bug("[AHCI>>]:-ahci_RegisterVolume: '%s' C/H/S=%d/%d/%d, %s unit %d\n",
269 AROS_BSTR_ADDR(devnode
->dn_Name
), at
->at_identify
.ncyls
, at
->at_identify
.nheads
, at
->at_identify
.nsectors
, MOD_NAME_STRING
, unit
));
270 AddBootNode(pp
[DE_BOOTPRI
+ 4], 0, devnode
, 0);
271 D(bug("[AHCI>>]:-ahci_RegisterVolume: done\n"));
275 CloseLibrary((struct Library
*)ExpansionBase
);
282 int ahci_cam_attach(struct ahci_port
*ap
)
286 D(bug("ahci_cam_attach: port %p\n", ap
));
288 ahci_os_unlock_port(ap
);
289 lockmgr(&ap
->ap_sim_lock
, LK_EXCLUSIVE
);
290 error
= ahci_RegisterPort(ap
);
291 lockmgr(&ap
->ap_sim_lock
, LK_RELEASE
);
292 ahci_os_lock_port(ap
);
297 ap
->ap_flags
|= AP_F_BUS_REGISTERED
;
299 if (ap
->ap_probe
== ATA_PROBE_NEED_IDENT
)
300 error
= ahci_cam_probe(ap
, NULL
);
308 ap
->ap_flags
|= AP_F_CAM_ATTACHED
;
313 void ahci_cam_detach(struct ahci_port
*ap
)
315 D(bug("ahci_cam_detach: port %p\n", ap
));
317 lockmgr(&ap
->ap_sim_lock
, LK_EXCLUSIVE
);
318 if (ap
->ap_flags
& AP_F_BUS_REGISTERED
) {
319 ap
->ap_flags
&= ~AP_F_BUS_REGISTERED
;
322 ahci_UnregisterPort(ap
);
324 lockmgr(&ap
->ap_sim_lock
, LK_RELEASE
);
325 ap
->ap_flags
&= ~AP_F_CAM_ATTACHED
;
329 * The state of the port has changed.
331 * If atx is NULL the physical port has changed state.
332 * If atx is non-NULL a particular target behind a PM has changed state.
334 * If found is -1 the target state must be queued to a non-interrupt context.
335 * (only works with at == NULL).
337 * If found is 0 the target was removed.
338 * If found is 1 the target was inserted.
340 void ahci_cam_changed(struct ahci_port
*ap
, struct ata_port
*atx
, int found
)
342 D(bug("ahci_cam_changed: ap=%p, sim = %p, atx=%p, found=%d\n", ap
, ap
->ap_sim
, atx
, found
));
346 ap
->ap_sim
->sim_Flags
|= SIMF_OffLine
;
348 ap
->ap_sim
->sim_Flags
&= ~SIMF_OffLine
;
352 /* Mark the port scan as completed */
353 ap
->ap_flags
|= AP_F_SCAN_COMPLETED
;
356 static void ahci_strip_string(const char **basep
, int *lenp
)
358 const char *base
= *basep
;
361 while (len
&& (*base
== 0 || *base
== ' ')) {
365 while (len
&& (base
[len
-1] == 0 || base
[len
-1] == ' '))
371 static u_int16_t
bswap16(u_int16_t word
)
373 return ((word
<< 8) & 0xff00) |
374 ((word
>> 8) & 0x00ff);
378 * Fix byte ordering so buffers can be accessed as
382 ata_fix_identify(struct ata_identify
*id
)
387 swap
= (u_int16_t
*)id
->serial
;
388 for (i
= 0; i
< sizeof(id
->serial
) / sizeof(u_int16_t
); i
++)
389 swap
[i
] = bswap16(swap
[i
]);
391 swap
= (u_int16_t
*)id
->firmware
;
392 for (i
= 0; i
< sizeof(id
->firmware
) / sizeof(u_int16_t
); i
++)
393 swap
[i
] = bswap16(swap
[i
]);
395 swap
= (u_int16_t
*)id
->model
;
396 for (i
= 0; i
< sizeof(id
->model
) / sizeof(u_int16_t
); i
++)
397 swap
[i
] = bswap16(swap
[i
]);
401 * Dummy done callback for xa.
403 static void ahci_ata_dummy_done(struct ata_xfer
*xa
)
408 * Setting the transfer mode is irrelevant for the SATA transport
409 * but some (atapi) devices seem to need it anyway. In addition
410 * if we are running through a SATA->PATA converter for some reason
411 * beyond my comprehension we might have to set the mode.
413 * We only support DMA modes for SATA attached devices, so don't bother
417 ahci_set_xfer(struct ahci_port
*ap
, struct ata_port
*atx
)
424 at
= atx
? atx
: ap
->ap_ata
[0];
427 * Figure out the supported UDMA mode. Ignore other legacy modes.
429 mask
= le16toh(at
->at_identify
.ultradma
);
430 if ((mask
& 0xFF) == 0 || mask
== 0xFFFF)
434 while ((mask
& 0x8000) == 0) {
440 * SATA atapi devices often still report a dma mode, even though
441 * it is irrelevant for SATA transport. It is also possible that
442 * we are running through a SATA->PATA converter and seeing the
445 * In this case the device may require a (dummy) SETXFER to be
446 * sent before it will work properly.
448 xa
= ahci_ata_get_xfer(ap
, atx
);
449 xa
->complete
= ahci_ata_dummy_done
;
450 xa
->fis
->command
= ATA_C_SET_FEATURES
;
451 xa
->fis
->features
= ATA_SF_SETXFER
;
452 xa
->fis
->flags
= ATA_H2D_FLAGS_CMD
| at
->at_target
;
453 xa
->fis
->sector_count
= mode
;
454 xa
->flags
= ATA_F_PIO
| ATA_F_POLL
;
457 if (ahci_ata_cmd(xa
) != ATA_S_COMPLETE
) {
458 kprintf("%s: Unable to set dummy xfer mode \n",
460 } else if (bootverbose
) {
461 kprintf("%s: Set dummy xfer mode to %02x\n",
462 ATANAME(ap
, atx
), mode
);
464 ahci_ata_put_xfer(xa
);
470 * DISK-specific probe after initial ident
473 ahci_cam_probe_disk(struct ahci_port
*ap
, struct ata_port
*atx
)
478 at
= atx
? atx
: ap
->ap_ata
[0];
481 * Set dummy xfer mode
483 ahci_set_xfer(ap
, atx
);
486 * Enable write cache if supported
488 * NOTE: "WD My Book" external disk devices have a very poor
489 * daughter board between the the ESATA and the HD. Sending
490 * any ATA_C_SET_FEATURES commands will break the hardware port
491 * with a fatal protocol error. However, this device also
492 * indicates that WRITECACHE is already on and READAHEAD is
493 * not supported so we avoid the issue.
495 if ((at
->at_identify
.cmdset82
& ATA_IDENTIFY_WRITECACHE
) &&
496 (at
->at_identify
.features85
& ATA_IDENTIFY_WRITECACHE
) == 0) {
497 xa
= ahci_ata_get_xfer(ap
, atx
);
498 xa
->complete
= ahci_ata_dummy_done
;
499 xa
->fis
->command
= ATA_C_SET_FEATURES
;
500 xa
->fis
->features
= ATA_SF_WRITECACHE_EN
;
501 /* xa->fis->features = ATA_SF_LOOKAHEAD_EN; */
502 xa
->fis
->flags
= ATA_H2D_FLAGS_CMD
| at
->at_target
;
504 xa
->flags
= ATA_F_PIO
| ATA_F_POLL
;
507 if (ahci_ata_cmd(xa
) == ATA_S_COMPLETE
)
508 at
->at_features
|= ATA_PORT_F_WCACHE
;
510 kprintf("%s: Unable to enable write-caching\n",
512 ahci_ata_put_xfer(xa
);
516 * Enable readahead if supported
518 if ((at
->at_identify
.cmdset82
& ATA_IDENTIFY_LOOKAHEAD
) &&
519 (at
->at_identify
.features85
& ATA_IDENTIFY_LOOKAHEAD
) == 0) {
520 xa
= ahci_ata_get_xfer(ap
, atx
);
521 xa
->complete
= ahci_ata_dummy_done
;
522 xa
->fis
->command
= ATA_C_SET_FEATURES
;
523 xa
->fis
->features
= ATA_SF_LOOKAHEAD_EN
;
524 xa
->fis
->flags
= ATA_H2D_FLAGS_CMD
| at
->at_target
;
526 xa
->flags
= ATA_F_PIO
| ATA_F_POLL
;
529 if (ahci_ata_cmd(xa
) == ATA_S_COMPLETE
)
530 at
->at_features
|= ATA_PORT_F_RAHEAD
;
532 kprintf("%s: Unable to enable read-ahead\n",
534 ahci_ata_put_xfer(xa
);
538 * FREEZE LOCK the device so malicious users can't lock it on us.
539 * As there is no harm in issuing this to devices that don't
540 * support the security feature set we just send it, and don't bother
541 * checking if the device sends a command abort to tell us it doesn't
544 if ((at
->at_identify
.cmdset82
& ATA_IDENTIFY_SECURITY
) &&
545 (at
->at_identify
.securestatus
& ATA_SECURE_FROZEN
) == 0 &&
546 (AhciNoFeatures
& (1 << ap
->ap_num
)) == 0) {
547 xa
= ahci_ata_get_xfer(ap
, atx
);
548 xa
->complete
= ahci_ata_dummy_done
;
549 xa
->fis
->command
= ATA_C_SEC_FREEZE_LOCK
;
550 xa
->fis
->flags
= ATA_H2D_FLAGS_CMD
| at
->at_target
;
551 xa
->flags
= ATA_F_PIO
| ATA_F_POLL
;
554 if (ahci_ata_cmd(xa
) == ATA_S_COMPLETE
)
555 at
->at_features
|= ATA_PORT_F_FRZLCK
;
557 kprintf("%s: Unable to set security freeze\n",
559 ahci_ata_put_xfer(xa
);
562 /* Fix up sector size, if the Word 106 is valid */
563 if ((at
->at_identify
.phys_sect_sz
& 0xc000) == 0x4000) {
564 /* Physical sector size is longer than 256 16-bit words? */
565 if (at
->at_identify
.phys_sect_sz
& (1 << 12)) {
568 logsize
= at
->at_identify
.words_lsec
[0];
570 logsize
+= at
->at_identify
.words_lsec
[1];
571 D(physize
= logsize
>> (at
->at_identify
.phys_sect_sz
& 3));
572 D(kprintf("%s: Logical sector size: %d bytes\n",
573 ATANAME(ap
, atx
), logsize
* 2));
574 D(kprintf("%s: Physical sector size: %d bytes\n",
575 ATANAME(ap
, atx
), physize
* 2));
576 at
->at_identify
.sector_size
= logsize
* 2;
578 D(kprintf("%s: Physical sector size == Logical sector size\n", ATANAME(ap
, atx
)));
579 at
->at_identify
.sector_size
= 256 * 2;
582 kprintf("%s: ATA IDENTIFY: Invalid Word 106: 0x%04x\n", ATANAME(ap
, atx
), at
->at_identify
.phys_sect_sz
);
583 at
->at_identify
.sector_size
= 256 * 2;
585 D(kprintf("%s: Sector size: %d bytes\n", ATANAME(ap
, atx
), at
->at_identify
.sector_size
));
587 #if 1 /* Temporary debugging... */
589 kprintf("%s: ATA IDENTIFY\n", ATANAME(ap
, atx
));
590 for (i
= 0; i
< 128; i
++) {
591 if ((i
%8) == 0) kprintf("%s %3d:", ATANAME(ap
, atx
), i
);
592 kprintf(" %04x", ((uint16_t *)(&at
->at_identify
))[i
]);
593 if ((i
%8) == 7) kprintf("\n");
601 * ATAPI-specific probe after initial ident
604 ahci_cam_probe_atapi(struct ahci_port
*ap
, struct ata_port
*atx
)
606 ahci_set_xfer(ap
, atx
);
612 * Once the AHCI port has been attached we need to probe for a device or
613 * devices on the port and setup various options.
615 * If at is NULL we are probing the direct-attached device on the port,
616 * which may or may not be a port multiplier.
619 ahci_cam_probe(struct ahci_port
*ap
, struct ata_port
*atx
)
624 u_int64_t capacity_bytes
;
631 const char *model_id
;
632 const char *firmware_id
;
633 const char *serial_id
;
642 * A NULL atx indicates a probe of the directly connected device.
643 * A non-NULL atx indicates a device connected via a port multiplier.
644 * We need to preserve atx for calls to ahci_ata_get_xfer().
646 * at is always non-NULL. For directly connected devices we supply
647 * an (at) pointing to target 0.
650 at
= ap
->ap_ata
[0]; /* direct attached - device 0 */
651 if (ap
->ap_type
== ATA_PORT_T_PM
) {
652 kprintf("%s: Found Port Multiplier\n",
656 at
->at_type
= ap
->ap_type
;
659 if (atx
->at_type
== ATA_PORT_T_PM
) {
660 kprintf("%s: Bogus device, reducing port count to %d\n",
661 ATANAME(ap
, atx
), atx
->at_target
);
662 if (ap
->ap_pmcount
> atx
->at_target
)
663 ap
->ap_pmcount
= atx
->at_target
;
667 if (ap
->ap_type
== ATA_PORT_T_NONE
)
669 if (at
->at_type
== ATA_PORT_T_NONE
)
673 * Issue identify, saving the result
675 xa
= ahci_ata_get_xfer(ap
, atx
);
676 xa
->complete
= ahci_ata_dummy_done
;
677 xa
->data
= &at
->at_identify
;
678 xa
->datalen
= sizeof(at
->at_identify
);
679 xa
->flags
= ATA_F_READ
| ATA_F_PIO
| ATA_F_POLL
;
680 xa
->fis
->flags
= ATA_H2D_FLAGS_CMD
| at
->at_target
;
682 switch(at
->at_type
) {
683 case ATA_PORT_T_DISK
:
684 xa
->fis
->command
= ATA_C_IDENTIFY
;
687 case ATA_PORT_T_ATAPI
:
688 xa
->fis
->command
= ATA_C_ATAPI_IDENTIFY
;
689 xa
->flags
|= ATA_F_AUTOSENSE
;
693 xa
->fis
->command
= ATA_C_ATAPI_IDENTIFY
;
694 type
= "UNKNOWN(ATAPI?)";
697 xa
->fis
->features
= 0;
701 if (ahci_ata_cmd(xa
) != ATA_S_COMPLETE
) {
702 kprintf("%s: Detected %s device but unable to IDENTIFY\n",
703 ATANAME(ap
, atx
), type
);
704 ahci_ata_put_xfer(xa
);
707 ahci_ata_put_xfer(xa
);
709 ata_fix_identify(&at
->at_identify
);
712 * Read capacity using SATA probe info.
714 if (le16toh(at
->at_identify
.cmdset83
) & 0x0400) {
715 /* LBA48 feature set supported */
717 for (i
= 3; i
>= 0; --i
) {
720 le16toh(at
->at_identify
.addrsecxt
[i
]);
723 capacity
= le16toh(at
->at_identify
.addrsec
[1]);
725 capacity
+= le16toh(at
->at_identify
.addrsec
[0]);
728 capacity
= 1024 * 1024 / 512;
729 at
->at_capacity
= capacity
;
731 ap
->ap_probe
= ATA_PROBE_GOOD
;
733 capacity_bytes
= capacity
* 512;
736 * Negotiate NCQ, throw away any ata_xfer's beyond the negotiated
737 * number of slots and limit the number of CAM ccb's to one less
738 * so we always have a slot available for recovery.
740 * NCQ is not used if ap_ncqdepth is 1 or the host controller does
741 * not support it, and in that case the driver can handle extra
744 * NCQ is currently used only with direct-attached disks. It is
745 * not used with port multipliers or direct-attached ATAPI devices.
747 * Remember at least one extra CCB needs to be reserved for the
750 if ((ap
->ap_sc
->sc_cap
& AHCI_REG_CAP_SNCQ
) &&
751 ap
->ap_type
== ATA_PORT_T_DISK
&&
752 (le16toh(at
->at_identify
.satacap
) & (1 << 8))) {
753 at
->at_ncqdepth
= (le16toh(at
->at_identify
.qdepth
) & 0x1F) + 1;
754 devncqdepth
= at
->at_ncqdepth
;
755 if (at
->at_ncqdepth
> ap
->ap_sc
->sc_ncmds
)
756 at
->at_ncqdepth
= ap
->ap_sc
->sc_ncmds
;
757 if (at
->at_ncqdepth
> 1) {
758 for (i
= 0; i
< ap
->ap_sc
->sc_ncmds
; ++i
) {
759 xa
= ahci_ata_get_xfer(ap
, atx
);
760 if (xa
->tag
< at
->at_ncqdepth
) {
761 xa
->state
= ATA_S_COMPLETE
;
762 ahci_ata_put_xfer(xa
);
766 if (at
->at_ncqdepth
>= ap
->ap_sc
->sc_ncmds
) {
767 cam_sim_set_max_tags(ap
->ap_sim
,
768 at
->at_ncqdepth
- 1);
776 model_len
= sizeof(at
->at_identify
.model
);
777 model_id
= at
->at_identify
.model
;
778 ahci_strip_string(&model_id
, &model_len
);
780 firmware_len
= sizeof(at
->at_identify
.firmware
);
781 firmware_id
= at
->at_identify
.firmware
;
782 ahci_strip_string(&firmware_id
, &firmware_len
);
784 serial_len
= sizeof(at
->at_identify
.serial
);
785 serial_id
= at
->at_identify
.serial
;
786 ahci_strip_string(&serial_id
, &serial_len
);
789 * Generate informatiive strings.
791 * NOTE: We do not automatically set write caching, lookahead,
792 * or the security state for ATAPI devices.
794 if (at
->at_identify
.cmdset82
& ATA_IDENTIFY_WRITECACHE
) {
795 if (at
->at_identify
.features85
& ATA_IDENTIFY_WRITECACHE
)
797 else if (at
->at_type
== ATA_PORT_T_ATAPI
)
805 if (at
->at_identify
.cmdset82
& ATA_IDENTIFY_LOOKAHEAD
) {
806 if (at
->at_identify
.features85
& ATA_IDENTIFY_LOOKAHEAD
)
808 else if (at
->at_type
== ATA_PORT_T_ATAPI
)
816 if (at
->at_identify
.cmdset82
& ATA_IDENTIFY_SECURITY
) {
817 if (at
->at_identify
.securestatus
& ATA_SECURE_FROZEN
)
819 else if (at
->at_type
== ATA_PORT_T_ATAPI
)
821 else if (AhciNoFeatures
& (1 << ap
->ap_num
))
822 scstr
= "<disabled>";
829 kprintf("%s: Found %s \"%*.*s %*.*s\" serial=\"%*.*s\"\n"
830 "%s: tags=%d/%d satacap=%04x satafea=%04x NCQ=%s "
831 "capacity=%lld.%02dMB\n",
835 model_len
, model_len
, model_id
,
836 firmware_len
, firmware_len
, firmware_id
,
837 serial_len
, serial_len
, serial_id
,
840 devncqdepth
, ap
->ap_sc
->sc_ncmds
,
841 at
->at_identify
.satacap
,
842 at
->at_identify
.satafsup
,
843 (at
->at_ncqdepth
> 1 ? "YES" : "NO"),
844 (long long)capacity_bytes
/ (1024 * 1024),
845 (int)(capacity_bytes
% (1024 * 1024)) * 100 / (1024 * 1024)
847 kprintf("%s: f85=%04x f86=%04x f87=%04x WC=%s RA=%s SEC=%s\n",
849 at
->at_identify
.features85
,
850 at
->at_identify
.features86
,
851 at
->at_identify
.features87
,
858 * Additional type-specific probing
860 switch(at
->at_type
) {
861 case ATA_PORT_T_DISK
:
862 error
= ahci_cam_probe_disk(ap
, atx
);
864 case ATA_PORT_T_ATAPI
:
865 error
= ahci_cam_probe_atapi(ap
, atx
);
873 at
->at_probe
= ATA_PROBE_FAILED
;
875 ap
->ap_probe
= at
->at_probe
;
877 at
->at_probe
= ATA_PROBE_GOOD
;
879 ap
->ap_probe
= at
->at_probe
;
880 ahci_RegisterVolume(ap
, at
);