2 * Copyright (C) 2012-2018, 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>
10 #include <proto/exec.h>
12 /* We want all other bases obtained from our base */
15 #include <aros/atomic.h>
17 #include <proto/expansion.h>
18 #include <proto/dos.h>
20 #include <dos/filehandler.h>
22 #include <devices/trackdisk.h>
23 #include <devices/scsidisk.h>
25 #include <scsi/commands.h>
26 #include <scsi/values.h>
29 #include "ahci_scsi.h"
32 #include LC_LIBDEFS_FILE
35 * Execute a SCSI TEST UNIT READY every 250ms, to see
36 * if the medium has changed.
38 static void ahci_PortMonitor(struct Task
*parent
, struct Device
*device
, struct cam_sim
*unit
)
41 struct IORequest
*tmr
;
43 D(bug("%s %d: Monitor Start\n", ((struct Node
*)device
)->ln_Name
, unit
->sim_Unit
));
44 AROS_ATOMIC_INC(unit
->sim_UseCount
);
45 Signal(parent
, SIGBREAKF_CTRL_C
);
47 tmr
= ahci_OpenTimer();
51 if ((mp
= CreateMsgPort())) {
53 if ((io
= CreateIORequest(mp
, sizeof(struct IOStdReq
)))) {
54 BOOL media_present
= FALSE
;
56 struct scsi_generic test_unit_ready
= { .opcode
= SCSI_TEST_UNIT_READY
, };
57 struct scsi_sense_data sense
= {};
58 struct SCSICmd scsi
= {};
60 io
->io_Device
= device
;
61 io
->io_Unit
= (struct Unit
*)unit
;
63 D(bug("%s %d: Monitoring\n", ((struct Node
*)device
)->ln_Name
, unit
->sim_Unit
));
67 io
->io_Command
= HD_SCSICMD
;
70 IOStdReq(io
)->io_Data
= &scsi
;
71 IOStdReq(io
)->io_Length
= sizeof(scsi
);
72 IOStdReq(io
)->io_Actual
= 0;
73 scsi
.scsi_Command
= (UBYTE
*)&test_unit_ready
;
74 scsi
.scsi_CmdLength
= sizeof(test_unit_ready
);
77 scsi
.scsi_Flags
= SCSIF_AUTOSENSE
;
78 scsi
.scsi_SenseData
= (UBYTE
*)&sense
;
79 scsi
.scsi_SenseLength
= sizeof(sense
);
80 scsi
.scsi_SenseActual
= 0;
84 is_present
= (io
->io_Error
== 0) && (scsi
.scsi_Status
== SCSI_GOOD
);
85 // TODO: Check sense for additional information
87 ObtainSemaphore(&unit
->sim_Lock
);
89 unit
->sim_Flags
|= SIMF_MediaPresent
;
91 unit
->sim_Flags
&= ~SIMF_MediaPresent
;
92 if (is_present
!= media_present
)
93 unit
->sim_ChangeNum
++;
94 ReleaseSemaphore(&unit
->sim_Lock
);
96 if (is_present
!= media_present
) {
97 struct IORequest
*msg
;
99 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"));
102 ForeachNode((struct Node
*)&unit
->sim_IOs
, msg
) {
103 D(bug("%s %d: io_Command = 0x%04x\n", ((struct Node
*)device
)->ln_Name
, unit
->sim_Unit
, msg
->io_Command
));
104 if (msg
->io_Command
== TD_ADDCHANGEINT
) {
105 D(bug("%s %d: Interrupt = 0x%p\n", ((struct Node
*)device
)->ln_Name
, unit
->sim_Unit
, IOStdReq(msg
)->io_Data
));
106 Cause((struct Interrupt
*)IOStdReq(msg
)->io_Data
);
111 media_present
= is_present
;
113 /* Wait 1s to the next scan */
114 } while ((ahci_WaitTO(tmr
, 1, 0, SIGF_DOS
) & SIGF_DOS
) == 0);
120 AROS_ATOMIC_DEC(unit
->sim_UseCount
);
121 D(bug("%s %d: Monitor End\n", ((struct Node
*)device
)->ln_Name
, unit
->sim_Unit
));
124 static int ahci_RegisterPort(struct ahci_port
*ap
)
126 struct AHCIBase
*AHCIBase
= ap
->ap_sc
->sc_dev
->dev_AHCIBase
;
127 struct cam_sim
*unit
;
129 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__
));
131 unit
= AllocPooled(AHCIBase
->ahci_MemPool
, sizeof(*unit
));
137 unit
->sim_Unit
= ap
->ap_sc
->sc_dev
->dev_HostID
* 32 + ap
->ap_num
;
138 InitSemaphore(&unit
->sim_Lock
);
139 NEWLIST(&unit
->sim_IOs
);
141 AddTail((struct List
*)&AHCIBase
->ahci_Units
, (struct Node
*)unit
);
143 /* Now that this device is in the unit list, start the disk change monitor */
144 snprintf(name
, sizeof(name
), "ahci.device %d [media]", unit
->sim_Unit
);
145 unit
->sim_Monitor
= NewCreateTask(TASKTAG_NAME
, name
,
146 TASKTAG_PC
, ahci_PortMonitor
,
147 TASKTAG_ARG1
, FindTask(NULL
),
148 TASKTAG_ARG2
, AHCIBase
,
152 Wait(SIGBREAKF_CTRL_C
);
157 static int ahci_UnregisterPort(struct ahci_port
*ap
)
159 struct ahci_softc
*sc
= ap
->ap_sc
;
160 struct AHCIBase
*AHCIBase
;
161 struct cam_sim
*unit
= ap
->ap_sim
;
163 D(bug("[AHCI] ahci_UnregisterPort: %p\n", ap
));
166 D(bug("No softc?\n"));
170 AHCIBase
= sc
->sc_dev
->dev_AHCIBase
;
172 /* Stop the monitor, and wait for IOs to drain,
173 * and users to CloseDevice() the unit.
175 if (unit
->sim_Monitor
)
176 Signal(unit
->sim_Monitor
, SIGF_DOS
);
177 ObtainSemaphore(&unit
->sim_Lock
);
178 while (unit
->sim_UseCount
) {
179 ReleaseSemaphore(&unit
->sim_Lock
);
181 ObtainSemaphore(&unit
->sim_Lock
);
183 ReleaseSemaphore(&unit
->sim_Lock
);
185 /* Remove from the unit list */
187 Remove((struct Node
*)unit
);
190 FreePooled(AHCIBase
->ahci_MemPool
, unit
, sizeof(*unit
));
195 /* Add a bootnode using expansion.library,
196 * but only when dos.library has not yet been initialized.
197 * This way, we get BootNodes if ahci.device is linked in,
198 * but don't if ahci.device is loaded after booting.
200 static BOOL
ahci_RegisterVolume(struct ahci_port
*ap
, struct ata_port
*at
, struct ahci_Unit
*unit
)
202 struct ExpansionBase
*ExpansionBase
;
204 struct DeviceNode
*devnode
;
205 TEXT dosdevname
[4] = "HA0";
206 const ULONG DOS_ID
= AROS_MAKE_ID('D','O','S','\001');
207 const ULONG CDROM_ID
= AROS_MAKE_ID('C','D','V','D');
209 unit
->au_UnitNum
= device_get_unit(ap
->ap_sc
->sc_dev
) * 32 + ap
->ap_num
;
211 D(bug("[AHCI>>] %s()\n", __PRETTY_FUNCTION__
));
212 D(bug("[AHCI>>] %s: ap = %p, at = %p, unit = %d\n", __func__
, ap
, at
, ap
->ap_sim
? ap
->ap_sim
->sim_Unit
: -1));
214 /* See if dos.library has run */
216 dos_loaded
= (FindName (&SysBase
->LibList
, "dos.library") != NULL
);
220 D(bug("[AHCI>>] %s: refused to register as boot volume - dos.library already loaded\n", __func__
));
224 if (at
== NULL
|| ap
->ap_type
== ATA_PORT_T_NONE
)
227 /* This should be dealt with using some sort of volume manager or such. */
230 case ATA_PORT_T_DISK
:
232 case ATA_PORT_T_ATAPI
:
236 D(bug("[AHCI>>]:-ahci_RegisterVolume called on unknown devicetype\n"));
240 ExpansionBase
= (struct ExpansionBase
*)OpenLibrary("expansion.library",
245 IPTR pp
[4 + DE_BOOTBLOCKS
+ 1];
248 dosdevname
[2] += ap
->ap_num
;
250 dosdevname
[2] = 'A' + (ap
->ap_num
- 10);
252 pp
[0] = (IPTR
)dosdevname
;
253 pp
[1] = (IPTR
)MOD_NAME_STRING
;
254 pp
[2] = unit
->au_UnitNum
;
255 pp
[DE_TABLESIZE
+ 4] = DE_BOOTBLOCKS
;
256 pp
[DE_SIZEBLOCK
+ 4] = at
->at_identify
.sector_size
;
257 pp
[DE_NUMHEADS
+ 4] = at
->at_identify
.nheads
;
258 pp
[DE_SECSPERBLOCK
+ 4] = 1;
259 pp
[DE_BLKSPERTRACK
+ 4] = at
->at_identify
.nsectors
;
260 pp
[DE_RESERVEDBLKS
+ 4] = 2;
261 pp
[DE_LOWCYL
+ 4] = 0;
262 pp
[DE_HIGHCYL
+ 4] = (ap
->ap_type
== ATA_PORT_T_DISK
) ? (at
->at_identify
.ncyls
-1) : 0;
263 pp
[DE_NUMBUFFERS
+ 4] = 10;
264 pp
[DE_BUFMEMTYPE
+ 4] = MEMF_PUBLIC
;
265 pp
[DE_MAXTRANSFER
+ 4] = 0x00200000;
266 pp
[DE_MASK
+ 4] = ~3;
267 pp
[DE_BOOTPRI
+ 4] = (ap
->ap_type
== ATA_PORT_T_DISK
) ? 0 : 10;
268 pp
[DE_DOSTYPE
+ 4] = (ap
->ap_type
== ATA_PORT_T_DISK
) ? DOS_ID
: CDROM_ID
;
270 pp
[DE_CONTROL
+ 4] = 0;
271 pp
[DE_BOOTBLOCKS
+ 4] = 2;
273 devnode
= MakeDosNode(pp
);
276 D(bug("[AHCI>>]:-ahci_RegisterVolume: '%s' C/H/S=%d/%d/%d, %s unit->au_UnitNum %d\n",
277 AROS_BSTR_ADDR(devnode
->dn_Name
), at
->at_identify
.ncyls
, at
->at_identify
.nheads
, at
->at_identify
.nsectors
, MOD_NAME_STRING
, unit
->au_UnitNum
));
278 AddBootNode(pp
[DE_BOOTPRI
+ 4], 0, devnode
, 0);
279 D(bug("[AHCI>>]:-ahci_RegisterVolume: done\n"));
283 CloseLibrary((struct Library
*)ExpansionBase
);
290 int ahci_cam_attach(struct ahci_port
*ap
)
294 D(bug("[AHCI] ahci_cam_attach: port %p\n", ap
));
296 ahci_os_unlock_port(ap
);
297 lockmgr(&ap
->ap_sim_lock
, LK_EXCLUSIVE
);
298 error
= ahci_RegisterPort(ap
);
299 lockmgr(&ap
->ap_sim_lock
, LK_RELEASE
);
300 ahci_os_lock_port(ap
);
305 ap
->ap_flags
|= AP_F_BUS_REGISTERED
;
307 if (ap
->ap_probe
== ATA_PROBE_NEED_IDENT
)
308 error
= ahci_cam_probe(ap
, NULL
);
316 ap
->ap_flags
|= AP_F_CAM_ATTACHED
;
321 void ahci_cam_detach(struct ahci_port
*ap
)
323 D(bug("[AHCI] ahci_cam_detach: port %p\n", ap
));
325 lockmgr(&ap
->ap_sim_lock
, LK_EXCLUSIVE
);
326 if (ap
->ap_flags
& AP_F_BUS_REGISTERED
) {
327 ap
->ap_flags
&= ~AP_F_BUS_REGISTERED
;
330 ahci_UnregisterPort(ap
);
332 lockmgr(&ap
->ap_sim_lock
, LK_RELEASE
);
333 ap
->ap_flags
&= ~AP_F_CAM_ATTACHED
;
337 * The state of the port has changed.
339 * If atx is NULL the physical port has changed state.
340 * If atx is non-NULL a particular target behind a PM has changed state.
342 * If found is -1 the target state must be queued to a non-interrupt context.
343 * (only works with at == NULL).
345 * If found is 0 the target was removed.
346 * If found is 1 the target was inserted.
348 void ahci_cam_changed(struct ahci_port
*ap
, struct ata_port
*atx
, int found
)
350 D(bug("[AHCI] ahci_cam_changed: ap=%p, sim = %p, atx=%p, found=%d\n", ap
, ap
->ap_sim
, atx
, found
));
354 ap
->ap_sim
->sim_Flags
|= SIMF_OffLine
;
356 ap
->ap_sim
->sim_Flags
&= ~SIMF_OffLine
;
360 /* Mark the port scan as completed */
361 ap
->ap_flags
|= AP_F_SCAN_COMPLETED
;
364 static void ahci_strip_string(const char **basep
, int *lenp
)
366 const char *base
= *basep
;
369 while (len
&& (*base
== 0 || *base
== ' ')) {
373 while (len
&& (base
[len
-1] == 0 || base
[len
-1] == ' '))
379 static u_int16_t
bswap16(u_int16_t word
)
381 return ((word
<< 8) & 0xff00) |
382 ((word
>> 8) & 0x00ff);
386 * Fix byte ordering so buffers can be accessed as
390 ata_fix_identify(struct ata_identify
*id
)
394 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__
));
396 swap
= (u_int16_t
*)id
->serial
;
397 for (i
= 0; i
< sizeof(id
->serial
) / sizeof(u_int16_t
); i
++)
398 swap
[i
] = bswap16(swap
[i
]);
400 swap
= (u_int16_t
*)id
->firmware
;
401 for (i
= 0; i
< sizeof(id
->firmware
) / sizeof(u_int16_t
); i
++)
402 swap
[i
] = bswap16(swap
[i
]);
404 swap
= (u_int16_t
*)id
->model
;
405 for (i
= 0; i
< sizeof(id
->model
) / sizeof(u_int16_t
); i
++)
406 swap
[i
] = bswap16(swap
[i
]);
410 * Dummy done callback for xa.
412 static void ahci_ata_dummy_done(struct ata_xfer
*xa
)
417 * Setting the transfer mode is irrelevant for the SATA transport
418 * but some (atapi) devices seem to need it anyway. In addition
419 * if we are running through a SATA->PATA converter for some reason
420 * beyond my comprehension we might have to set the mode.
422 * We only support DMA modes for SATA attached devices, so don't bother
426 ahci_set_xfer(struct ahci_port
*ap
, struct ata_port
*atx
)
432 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__
));
434 at
= atx
? atx
: ap
->ap_ata
[0];
437 * Figure out the supported UDMA mode. Ignore other legacy modes.
439 mask
= le16toh(at
->at_identify
.ultradma
);
440 if ((mask
& 0xFF) == 0 || mask
== 0xFFFF)
444 while ((mask
& 0x8000) == 0) {
450 * SATA atapi devices often still report a dma mode, even though
451 * it is irrelevant for SATA transport. It is also possible that
452 * we are running through a SATA->PATA converter and seeing the
455 * In this case the device may require a (dummy) SETXFER to be
456 * sent before it will work properly.
458 xa
= ahci_ata_get_xfer(ap
, atx
);
459 xa
->complete
= ahci_ata_dummy_done
;
460 xa
->fis
->command
= ATA_C_SET_FEATURES
;
461 xa
->fis
->features
= ATA_SF_SETXFER
;
462 xa
->fis
->flags
= ATA_H2D_FLAGS_CMD
| at
->at_target
;
463 xa
->fis
->sector_count
= mode
;
464 xa
->flags
= ATA_F_PIO
| ATA_F_POLL
;
467 if (ahci_ata_cmd(xa
) != ATA_S_COMPLETE
) {
468 kprintf("%s: Unable to set dummy xfer mode \n",
470 } else if (bootverbose
) {
471 kprintf("%s: Set dummy xfer mode to %02x\n",
472 ATANAME(ap
, atx
), mode
);
474 ahci_ata_put_xfer(xa
);
480 * DISK-specific probe after initial ident
483 ahci_cam_probe_disk(struct ahci_port
*ap
, struct ata_port
*atx
)
487 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__
));
489 at
= atx
? atx
: ap
->ap_ata
[0];
492 * Set dummy xfer mode
494 ahci_set_xfer(ap
, atx
);
497 * Enable write cache if supported
499 * NOTE: "WD My Book" external disk devices have a very poor
500 * daughter board between the the ESATA and the HD. Sending
501 * any ATA_C_SET_FEATURES commands will break the hardware port
502 * with a fatal protocol error. However, this device also
503 * indicates that WRITECACHE is already on and READAHEAD is
504 * not supported so we avoid the issue.
506 if ((at
->at_identify
.cmdset82
& ATA_IDENTIFY_WRITECACHE
) &&
507 (at
->at_identify
.features85
& ATA_IDENTIFY_WRITECACHE
) == 0) {
508 xa
= ahci_ata_get_xfer(ap
, atx
);
509 xa
->complete
= ahci_ata_dummy_done
;
510 xa
->fis
->command
= ATA_C_SET_FEATURES
;
511 xa
->fis
->features
= ATA_SF_WRITECACHE_EN
;
512 /* xa->fis->features = ATA_SF_LOOKAHEAD_EN; */
513 xa
->fis
->flags
= ATA_H2D_FLAGS_CMD
| at
->at_target
;
515 xa
->flags
= ATA_F_PIO
| ATA_F_POLL
;
518 if (ahci_ata_cmd(xa
) == ATA_S_COMPLETE
)
519 at
->at_features
|= ATA_PORT_F_WCACHE
;
521 kprintf("%s: Unable to enable write-caching\n",
523 ahci_ata_put_xfer(xa
);
527 * Enable readahead if supported
529 if ((at
->at_identify
.cmdset82
& ATA_IDENTIFY_LOOKAHEAD
) &&
530 (at
->at_identify
.features85
& ATA_IDENTIFY_LOOKAHEAD
) == 0) {
531 xa
= ahci_ata_get_xfer(ap
, atx
);
532 xa
->complete
= ahci_ata_dummy_done
;
533 xa
->fis
->command
= ATA_C_SET_FEATURES
;
534 xa
->fis
->features
= ATA_SF_LOOKAHEAD_EN
;
535 xa
->fis
->flags
= ATA_H2D_FLAGS_CMD
| at
->at_target
;
537 xa
->flags
= ATA_F_PIO
| ATA_F_POLL
;
540 if (ahci_ata_cmd(xa
) == ATA_S_COMPLETE
)
541 at
->at_features
|= ATA_PORT_F_RAHEAD
;
543 kprintf("%s: Unable to enable read-ahead\n",
545 ahci_ata_put_xfer(xa
);
549 * FREEZE LOCK the device so malicious users can't lock it on us.
550 * As there is no harm in issuing this to devices that don't
551 * support the security feature set we just send it, and don't bother
552 * checking if the device sends a command abort to tell us it doesn't
555 if ((at
->at_identify
.cmdset82
& ATA_IDENTIFY_SECURITY
) &&
556 (at
->at_identify
.securestatus
& ATA_SECURE_FROZEN
) == 0 &&
557 (AhciNoFeatures
& (1 << ap
->ap_num
)) == 0) {
558 xa
= ahci_ata_get_xfer(ap
, atx
);
559 xa
->complete
= ahci_ata_dummy_done
;
560 xa
->fis
->command
= ATA_C_SEC_FREEZE_LOCK
;
561 xa
->fis
->flags
= ATA_H2D_FLAGS_CMD
| at
->at_target
;
562 xa
->flags
= ATA_F_PIO
| ATA_F_POLL
;
565 if (ahci_ata_cmd(xa
) == ATA_S_COMPLETE
)
566 at
->at_features
|= ATA_PORT_F_FRZLCK
;
568 kprintf("%s: Unable to set security freeze\n",
570 ahci_ata_put_xfer(xa
);
573 /* Fix up sector size, if the Word 106 is valid */
574 if ((at
->at_identify
.phys_sect_sz
& 0xc000) == 0x4000) {
575 /* Physical sector size is longer than 256 16-bit words? */
576 if (at
->at_identify
.phys_sect_sz
& (1 << 12)) {
579 logsize
= at
->at_identify
.words_lsec
[0];
581 logsize
+= at
->at_identify
.words_lsec
[1];
582 D(physize
= logsize
>> (at
->at_identify
.phys_sect_sz
& 3));
583 D(kprintf("%s: Logical sector size: %d bytes\n",
584 ATANAME(ap
, atx
), logsize
* 2));
585 D(kprintf("%s: Physical sector size: %d bytes\n",
586 ATANAME(ap
, atx
), physize
* 2));
587 at
->at_identify
.sector_size
= logsize
* 2;
589 D(kprintf("%s: Physical sector size == Logical sector size\n", ATANAME(ap
, atx
)));
590 at
->at_identify
.sector_size
= 256 * 2;
593 kprintf("%s: ATA IDENTIFY: Invalid Word 106: 0x%04x\n", ATANAME(ap
, atx
), at
->at_identify
.phys_sect_sz
);
594 at
->at_identify
.sector_size
= 256 * 2;
596 D(kprintf("%s: Sector size: %d bytes\n", ATANAME(ap
, atx
), at
->at_identify
.sector_size
));
598 #if 1 /* Temporary debugging... */
600 kprintf("%s: ATA IDENTIFY\n", ATANAME(ap
, atx
));
601 for (i
= 0; i
< 128; i
++) {
602 if ((i
%8) == 0) kprintf("%s %3d:", ATANAME(ap
, atx
), i
);
603 kprintf(" %04x", ((uint16_t *)(&at
->at_identify
))[i
]);
604 if ((i
%8) == 7) kprintf("\n");
612 * ATAPI-specific probe after initial ident
615 ahci_cam_probe_atapi(struct ahci_port
*ap
, struct ata_port
*atx
)
617 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__
));
618 ahci_set_xfer(ap
, atx
);
624 * Once the AHCI port has been attached we need to probe for a device or
625 * devices on the port and setup various options.
627 * If at is NULL we are probing the direct-attached device on the port,
628 * which may or may not be a port multiplier.
631 ahci_cam_probe(struct ahci_port
*ap
, struct ata_port
*atx
)
636 u_int64_t capacity_bytes
;
643 const char *model_id
;
644 const char *firmware_id
;
645 const char *serial_id
;
651 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__
));
655 * A NULL atx indicates a probe of the directly connected device.
656 * A non-NULL atx indicates a device connected via a port multiplier.
657 * We need to preserve atx for calls to ahci_ata_get_xfer().
659 * at is always non-NULL. For directly connected devices we supply
660 * an (at) pointing to target 0.
663 at
= ap
->ap_ata
[0]; /* direct attached - device 0 */
664 if (ap
->ap_type
== ATA_PORT_T_PM
) {
665 kprintf("%s: Found Port Multiplier\n",
669 at
->at_type
= ap
->ap_type
;
672 if (atx
->at_type
== ATA_PORT_T_PM
) {
673 kprintf("%s: Bogus device, reducing port count to %d\n",
674 ATANAME(ap
, atx
), atx
->at_target
);
675 if (ap
->ap_pmcount
> atx
->at_target
)
676 ap
->ap_pmcount
= atx
->at_target
;
680 if (ap
->ap_type
== ATA_PORT_T_NONE
)
682 if (at
->at_type
== ATA_PORT_T_NONE
)
686 * Issue identify, saving the result
688 xa
= ahci_ata_get_xfer(ap
, atx
);
689 xa
->complete
= ahci_ata_dummy_done
;
690 xa
->data
= &at
->at_identify
;
691 xa
->datalen
= sizeof(at
->at_identify
);
692 xa
->flags
= ATA_F_READ
| ATA_F_PIO
| ATA_F_POLL
;
693 xa
->fis
->flags
= ATA_H2D_FLAGS_CMD
| at
->at_target
;
695 switch(at
->at_type
) {
696 case ATA_PORT_T_DISK
:
697 xa
->fis
->command
= ATA_C_IDENTIFY
;
700 case ATA_PORT_T_ATAPI
:
701 xa
->fis
->command
= ATA_C_ATAPI_IDENTIFY
;
702 xa
->flags
|= ATA_F_AUTOSENSE
;
706 xa
->fis
->command
= ATA_C_ATAPI_IDENTIFY
;
707 type
= "UNKNOWN(ATAPI?)";
710 xa
->fis
->features
= 0;
714 if (ahci_ata_cmd(xa
) != ATA_S_COMPLETE
) {
715 kprintf("%s: Detected %s device but unable to IDENTIFY\n",
716 ATANAME(ap
, atx
), type
);
717 ahci_ata_put_xfer(xa
);
720 ahci_ata_put_xfer(xa
);
722 ata_fix_identify(&at
->at_identify
);
725 * Read capacity using SATA probe info.
727 if (le16toh(at
->at_identify
.cmdset83
) & 0x0400) {
728 /* LBA48 feature set supported */
730 for (i
= 3; i
>= 0; --i
) {
733 le16toh(at
->at_identify
.addrsecxt
[i
]);
736 capacity
= le16toh(at
->at_identify
.addrsec
[1]);
738 capacity
+= le16toh(at
->at_identify
.addrsec
[0]);
741 capacity
= 1024 * 1024 / 512;
742 at
->at_capacity
= capacity
;
744 ap
->ap_probe
= ATA_PROBE_GOOD
;
746 capacity_bytes
= capacity
* 512;
749 * Negotiate NCQ, throw away any ata_xfer's beyond the negotiated
750 * number of slots and limit the number of CAM ccb's to one less
751 * so we always have a slot available for recovery.
753 * NCQ is not used if ap_ncqdepth is 1 or the host controller does
754 * not support it, and in that case the driver can handle extra
757 * NCQ is currently used only with direct-attached disks. It is
758 * not used with port multipliers or direct-attached ATAPI devices.
760 * Remember at least one extra CCB needs to be reserved for the
763 if ((ap
->ap_sc
->sc_cap
& AHCI_REG_CAP_SNCQ
) &&
764 ap
->ap_type
== ATA_PORT_T_DISK
&&
765 (le16toh(at
->at_identify
.satacap
) & (1 << 8))) {
766 at
->at_ncqdepth
= (le16toh(at
->at_identify
.qdepth
) & 0x1F) + 1;
767 devncqdepth
= at
->at_ncqdepth
;
768 if (at
->at_ncqdepth
> ap
->ap_sc
->sc_ncmds
)
769 at
->at_ncqdepth
= ap
->ap_sc
->sc_ncmds
;
770 if (at
->at_ncqdepth
> 1) {
771 for (i
= 0; i
< ap
->ap_sc
->sc_ncmds
; ++i
) {
772 xa
= ahci_ata_get_xfer(ap
, atx
);
773 if (xa
->tag
< at
->at_ncqdepth
) {
774 xa
->state
= ATA_S_COMPLETE
;
775 ahci_ata_put_xfer(xa
);
779 if (at
->at_ncqdepth
>= ap
->ap_sc
->sc_ncmds
) {
780 cam_sim_set_max_tags(ap
->ap_sim
,
781 at
->at_ncqdepth
- 1);
789 model_len
= sizeof(at
->at_identify
.model
);
790 model_id
= at
->at_identify
.model
;
791 ahci_strip_string(&model_id
, &model_len
);
793 firmware_len
= sizeof(at
->at_identify
.firmware
);
794 firmware_id
= at
->at_identify
.firmware
;
795 ahci_strip_string(&firmware_id
, &firmware_len
);
797 serial_len
= sizeof(at
->at_identify
.serial
);
798 serial_id
= at
->at_identify
.serial
;
799 ahci_strip_string(&serial_id
, &serial_len
);
802 * Generate informatiive strings.
804 * NOTE: We do not automatically set write caching, lookahead,
805 * or the security state for ATAPI devices.
807 if (at
->at_identify
.cmdset82
& ATA_IDENTIFY_WRITECACHE
) {
808 if (at
->at_identify
.features85
& ATA_IDENTIFY_WRITECACHE
)
810 else if (at
->at_type
== ATA_PORT_T_ATAPI
)
818 if (at
->at_identify
.cmdset82
& ATA_IDENTIFY_LOOKAHEAD
) {
819 if (at
->at_identify
.features85
& ATA_IDENTIFY_LOOKAHEAD
)
821 else if (at
->at_type
== ATA_PORT_T_ATAPI
)
829 if (at
->at_identify
.cmdset82
& ATA_IDENTIFY_SECURITY
) {
830 if (at
->at_identify
.securestatus
& ATA_SECURE_FROZEN
)
832 else if (at
->at_type
== ATA_PORT_T_ATAPI
)
834 else if (AhciNoFeatures
& (1 << ap
->ap_num
))
835 scstr
= "<disabled>";
842 kprintf("%s: Found %s \"%*.*s %*.*s\" serial=\"%*.*s\"\n"
843 "%s: tags=%d/%d satacap=%04x satafea=%04x NCQ=%s "
844 "capacity=%lld.%02dMB\n",
848 model_len
, model_len
, model_id
,
849 firmware_len
, firmware_len
, firmware_id
,
850 serial_len
, serial_len
, serial_id
,
853 devncqdepth
, ap
->ap_sc
->sc_ncmds
,
854 at
->at_identify
.satacap
,
855 at
->at_identify
.satafsup
,
856 (at
->at_ncqdepth
> 1 ? "YES" : "NO"),
857 (long long)capacity_bytes
/ (1024 * 1024),
858 (int)(capacity_bytes
% (1024 * 1024)) * 100 / (1024 * 1024)
860 kprintf("%s: f85=%04x f86=%04x f87=%04x WC=%s RA=%s SEC=%s\n",
862 at
->at_identify
.features85
,
863 at
->at_identify
.features86
,
864 at
->at_identify
.features87
,
871 * Additional type-specific probing
873 switch(at
->at_type
) {
874 case ATA_PORT_T_DISK
:
875 error
= ahci_cam_probe_disk(ap
, atx
);
877 case ATA_PORT_T_ATAPI
:
878 error
= ahci_cam_probe_atapi(ap
, atx
);
886 at
->at_probe
= ATA_PROBE_FAILED
;
888 ap
->ap_probe
= at
->at_probe
;
890 struct AHCIBase
*AHCIBase
= ap
->ap_sc
->sc_dev
->dev_AHCIBase
;
891 struct TagItem unitAttrs
[] =
893 {aHidd_DriverData
, (IPTR
)OOP_INST_DATA(AHCIBase
->busClass
, ap
->ap_Object
) },
897 struct ahci_Unit
*unit
;
899 at
->at_probe
= ATA_PROBE_GOOD
;
901 ap
->ap_probe
= at
->at_probe
;
903 unitObj
= OOP_NewObject(AHCIBase
->unitClass
, NULL
, unitAttrs
);
906 unit
= OOP_INST_DATA(AHCIBase
->unitClass
, unitObj
);
907 ahci_RegisterVolume(ap
, at
, unit
);