fix some flag usage in mmakefiles. provide suitable names for amiga hardware devices...
[AROS.git] / rom / devs / ahci / ahci_cam_aros.c
blobd5965a56524eae31558f883166e3dc198fd63d57
1 /*
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
6 */
8 #include <aros/debug.h>
10 #include <proto/exec.h>
12 /* We want all other bases obtained from our base */
13 #define __NOLIBBASE__
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>
28 #include "ahci.h"
29 #include "ahci_scsi.h"
30 #include "timer.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)
40 struct MsgPort *mp;
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();
48 if (!tmr)
49 return;
51 if ((mp = CreateMsgPort())) {
52 struct IORequest *io;
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));
64 do {
65 BOOL is_present;
67 io->io_Command = HD_SCSICMD;
68 io->io_Flags = 0;
69 io->io_Error = 0;
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);
75 scsi.scsi_Actual = 0;
76 scsi.scsi_Status = 0;
77 scsi.scsi_Flags = SCSIF_AUTOSENSE;
78 scsi.scsi_SenseData = (UBYTE *)&sense;
79 scsi.scsi_SenseLength = sizeof(sense);
80 scsi.scsi_SenseActual = 0;
82 DoIO(io);
84 is_present = (io->io_Error == 0) && (scsi.scsi_Status == SCSI_GOOD);
85 // TODO: Check sense for additional information
87 ObtainSemaphore(&unit->sim_Lock);
88 if (is_present)
89 unit->sim_Flags |= SIMF_MediaPresent;
90 else
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"));
101 Forbid();
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);
109 Permit();
111 media_present = is_present;
113 /* Wait 1s to the next scan */
114 } while ((ahci_WaitTO(tmr, 1, 0, SIGF_DOS) & SIGF_DOS) == 0);
116 DeleteIORequest(io);
118 DeleteMsgPort(mp);
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;
128 char name[64];
129 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__));
131 unit = AllocPooled(AHCIBase->ahci_MemPool, sizeof(*unit));
132 if (!unit)
133 return ENOMEM;
135 ap->ap_sim = unit;
136 unit->sim_Port = ap;
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,
149 TASKTAG_ARG3, unit,
150 TAG_END);
152 Wait(SIGBREAKF_CTRL_C);
154 return 0;
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));
165 if (sc == NULL) {
166 D(bug("No softc?\n"));
167 return 0;
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);
180 ahci_os_sleep(100);
181 ObtainSemaphore(&unit->sim_Lock);
183 ReleaseSemaphore(&unit->sim_Lock);
185 /* Remove from the unit list */
186 Forbid();
187 Remove((struct Node *)unit);
188 Permit();
190 FreePooled(AHCIBase->ahci_MemPool, unit, sizeof(*unit));
192 return 0;
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;
203 BOOL dos_loaded;
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 */
215 Forbid();
216 dos_loaded = (FindName (&SysBase->LibList, "dos.library") != NULL);
217 Permit();
219 if (dos_loaded) {
220 D(bug("[AHCI>>] %s: refused to register as boot volume - dos.library already loaded\n", __func__));
221 return FALSE;
224 if (at == NULL || ap->ap_type == ATA_PORT_T_NONE)
225 return FALSE;
227 /* This should be dealt with using some sort of volume manager or such. */
228 switch (ap->ap_type)
230 case ATA_PORT_T_DISK:
231 break;
232 case ATA_PORT_T_ATAPI:
233 dosdevname[0] = 'C';
234 break;
235 default:
236 D(bug("[AHCI>>]:-ahci_RegisterVolume called on unknown devicetype\n"));
237 return FALSE;
240 ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library",
241 40L);
243 if (ExpansionBase)
245 IPTR pp[4 + DE_BOOTBLOCKS + 1];
247 if (ap->ap_num < 10)
248 dosdevname[2] += ap->ap_num;
249 else
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;
269 pp[DE_BAUD + 4] = 0;
270 pp[DE_CONTROL + 4] = 0;
271 pp[DE_BOOTBLOCKS + 4] = 2;
273 devnode = MakeDosNode(pp);
275 if (devnode) {
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"));
280 return TRUE;
283 CloseLibrary((struct Library *)ExpansionBase);
286 return FALSE;
290 int ahci_cam_attach(struct ahci_port *ap)
292 int error;
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);
301 if (error) {
302 ahci_cam_detach(ap);
303 return (EINVAL);
305 ap->ap_flags |= AP_F_BUS_REGISTERED;
307 if (ap->ap_probe == ATA_PROBE_NEED_IDENT)
308 error = ahci_cam_probe(ap, NULL);
309 else
310 error = 0;
311 if (error) {
312 ahci_cam_detach(ap);
313 return (EIO);
316 ap->ap_flags |= AP_F_CAM_ATTACHED;
318 return 0;
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;
329 if (ap->ap_sim) {
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));
352 if (ap->ap_sim) {
353 if (found == 0) {
354 ap->ap_sim->sim_Flags |= SIMF_OffLine;
355 } else {
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;
367 int len = *lenp;
369 while (len && (*base == 0 || *base == ' ')) {
370 --len;
371 ++base;
373 while (len && (base[len-1] == 0 || base[len-1] == ' '))
374 --len;
375 *basep = base;
376 *lenp = len;
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
387 * strings.
389 static void
390 ata_fix_identify(struct ata_identify *id)
392 u_int16_t *swap;
393 int i;
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
423 * with legacy modes.
425 static int
426 ahci_set_xfer(struct ahci_port *ap, struct ata_port *atx)
428 struct ata_port *at;
429 struct ata_xfer *xa;
430 u_int16_t mode;
431 u_int16_t mask;
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)
441 return(0);
442 mask &= 0xFF;
443 mode = 0x4F;
444 while ((mask & 0x8000) == 0) {
445 mask <<= 1;
446 --mode;
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
453 * PATA dma mode.
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;
465 xa->timeout = 1000;
466 xa->datalen = 0;
467 if (ahci_ata_cmd(xa) != ATA_S_COMPLETE) {
468 kprintf("%s: Unable to set dummy xfer mode \n",
469 ATANAME(ap, atx));
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);
475 return(0);
480 * DISK-specific probe after initial ident
482 static int
483 ahci_cam_probe_disk(struct ahci_port *ap, struct ata_port *atx)
485 struct ata_port *at;
486 struct ata_xfer *xa;
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;
514 xa->fis->device = 0;
515 xa->flags = ATA_F_PIO | ATA_F_POLL;
516 xa->timeout = 1000;
517 xa->datalen = 0;
518 if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
519 at->at_features |= ATA_PORT_F_WCACHE;
520 else
521 kprintf("%s: Unable to enable write-caching\n",
522 ATANAME(ap, atx));
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;
536 xa->fis->device = 0;
537 xa->flags = ATA_F_PIO | ATA_F_POLL;
538 xa->timeout = 1000;
539 xa->datalen = 0;
540 if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
541 at->at_features |= ATA_PORT_F_RAHEAD;
542 else
543 kprintf("%s: Unable to enable read-ahead\n",
544 ATANAME(ap, atx));
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
553 * support it
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;
563 xa->timeout = 1000;
564 xa->datalen = 0;
565 if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
566 at->at_features |= ATA_PORT_F_FRZLCK;
567 else
568 kprintf("%s: Unable to set security freeze\n",
569 ATANAME(ap, atx));
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)) {
577 ULONG logsize;
578 D(ULONG physize;)
579 logsize = at->at_identify.words_lsec[0];
580 logsize <<= 16;
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;
588 } else {
589 D(kprintf("%s: Physical sector size == Logical sector size\n", ATANAME(ap, atx)));
590 at->at_identify.sector_size = 256 * 2;
592 } else {
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... */
599 int i;
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");
606 #endif
608 return (0);
612 * ATAPI-specific probe after initial ident
614 static int
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);
619 return(0);
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)
633 struct ata_port *at;
634 struct ata_xfer *xa;
635 u_int64_t capacity;
636 u_int64_t capacity_bytes;
637 int model_len;
638 int firmware_len;
639 int serial_len;
640 int error;
641 int devncqdepth;
642 int i;
643 const char *model_id;
644 const char *firmware_id;
645 const char *serial_id;
646 const char *wcstr;
647 const char *rastr;
648 const char *scstr;
649 const char *type;
651 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__));
652 error = EIO;
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.
662 if (atx == NULL) {
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",
666 ATANAME(ap, atx));
667 return (0);
669 at->at_type = ap->ap_type;
670 } else {
671 at = atx;
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;
677 goto err;
680 if (ap->ap_type == ATA_PORT_T_NONE)
681 goto err;
682 if (at->at_type == ATA_PORT_T_NONE)
683 goto err;
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;
698 type = "DISK";
699 break;
700 case ATA_PORT_T_ATAPI:
701 xa->fis->command = ATA_C_ATAPI_IDENTIFY;
702 xa->flags |= ATA_F_AUTOSENSE;
703 type = "ATAPI";
704 break;
705 default:
706 xa->fis->command = ATA_C_ATAPI_IDENTIFY;
707 type = "UNKNOWN(ATAPI?)";
708 break;
710 xa->fis->features = 0;
711 xa->fis->device = 0;
712 xa->timeout = 1000;
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);
718 goto err;
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 */
729 capacity = 0;
730 for (i = 3; i >= 0; --i) {
731 capacity <<= 16;
732 capacity +=
733 le16toh(at->at_identify.addrsecxt[i]);
735 } else {
736 capacity = le16toh(at->at_identify.addrsec[1]);
737 capacity <<= 16;
738 capacity += le16toh(at->at_identify.addrsec[0]);
740 if (capacity == 0)
741 capacity = 1024 * 1024 / 512;
742 at->at_capacity = capacity;
743 if (atx == NULL)
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
755 * ccb's.
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
761 * error ccb.
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);
778 #if 0
779 if (at->at_ncqdepth >= ap->ap_sc->sc_ncmds) {
780 cam_sim_set_max_tags(ap->ap_sim,
781 at->at_ncqdepth - 1);
783 #endif
785 } else {
786 devncqdepth = 0;
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)
809 wcstr = "enabled";
810 else if (at->at_type == ATA_PORT_T_ATAPI)
811 wcstr = "disabled";
812 else
813 wcstr = "enabling";
814 } else {
815 wcstr = "notsupp";
818 if (at->at_identify.cmdset82 & ATA_IDENTIFY_LOOKAHEAD) {
819 if (at->at_identify.features85 & ATA_IDENTIFY_LOOKAHEAD)
820 rastr = "enabled";
821 else if (at->at_type == ATA_PORT_T_ATAPI)
822 rastr = "disabled";
823 else
824 rastr = "enabling";
825 } else {
826 rastr = "notsupp";
829 if (at->at_identify.cmdset82 & ATA_IDENTIFY_SECURITY) {
830 if (at->at_identify.securestatus & ATA_SECURE_FROZEN)
831 scstr = "frozen";
832 else if (at->at_type == ATA_PORT_T_ATAPI)
833 scstr = "unfrozen";
834 else if (AhciNoFeatures & (1 << ap->ap_num))
835 scstr = "<disabled>";
836 else
837 scstr = "freezing";
838 } else {
839 scstr = "notsupp";
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",
846 ATANAME(ap, atx),
847 type,
848 model_len, model_len, model_id,
849 firmware_len, firmware_len, firmware_id,
850 serial_len, serial_len, serial_id,
852 ATANAME(ap, atx),
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",
861 ATANAME(ap, atx),
862 at->at_identify.features85,
863 at->at_identify.features86,
864 at->at_identify.features87,
865 wcstr,
866 rastr,
867 scstr
871 * Additional type-specific probing
873 switch(at->at_type) {
874 case ATA_PORT_T_DISK:
875 error = ahci_cam_probe_disk(ap, atx);
876 break;
877 case ATA_PORT_T_ATAPI:
878 error = ahci_cam_probe_atapi(ap, atx);
879 break;
880 default:
881 error = EIO;
882 break;
884 err:
885 if (error) {
886 at->at_probe = ATA_PROBE_FAILED;
887 if (atx == NULL)
888 ap->ap_probe = at->at_probe;
889 } else {
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) },
894 {TAG_DONE , 0 }
896 OOP_Object *unitObj;
897 struct ahci_Unit *unit;
899 at->at_probe = ATA_PROBE_GOOD;
900 if (atx == NULL)
901 ap->ap_probe = at->at_probe;
903 unitObj = OOP_NewObject(AHCIBase->unitClass, NULL, unitAttrs);
904 if (unitObj)
906 unit = OOP_INST_DATA(AHCIBase->unitClass, unitObj);
907 ahci_RegisterVolume(ap, at, unit);
910 return (error);