1111#pragma once
1212
1313#include <kernel.h>
14+ #include <scsi.h>
1415
1516/**
1617 * @brief Frame Information Structure (FIS) type identifiers.
@@ -331,8 +332,11 @@ typedef struct ahci_hba_cmd_tbl_t {
331332
332333/* ----------------------------- Interrupt/status and ATA opcodes ----------------------------- */
333334
334- /** @brief PxIS: Task File Error Status (TFES). */
335- #define HBA_PxIS_TFES (1 << 30)
335+ #define HBA_PxIS_TFES (1 << 30) /** Task file error */
336+ #define HBA_PxIS_IFS (1u << 27) /* Interface fatal error */
337+ #define HBA_PxIS_HBDS (1u << 28) /* Host bus data error */
338+ #define HBA_PxIS_HBFS (1u << 29) /* Host bus fatal error */
339+
336340/** @brief ATA command: READ DMA EXT (48-bit). */
337341#define ATA_CMD_READ_DMA_EX 0x25
338342/** @brief ATA command: WRITE DMA EXT (48-bit). */
@@ -392,7 +396,7 @@ int find_cmdslot(ahci_hba_port_t *port, ahci_hba_mem_t *abar);
392396 * @param abar AHCI HBA memory block.
393397 * @return true on success, false on error.
394398 */
395- bool ahci_read (ahci_hba_port_t * port , uint64_t start , uint32_t count , uint16_t * buf , ahci_hba_mem_t * abar );
399+ bool ahci_read (ahci_hba_port_t * port , uint64_t start , uint32_t count , char * buf , ahci_hba_mem_t * abar );
396400
397401/**
398402 * @brief Write to a SATA block device via DMA.
@@ -414,7 +418,7 @@ bool ahci_write(ahci_hba_port_t *port, uint64_t start, uint32_t count, char *buf
414418 * @param abar AHCI HBA memory block.
415419 * @return true on success, false on error.
416420 */
417- bool ahci_atapi_read (ahci_hba_port_t * port , uint64_t start , uint32_t count , uint16_t * buf , ahci_hba_mem_t * abar );
421+ bool ahci_atapi_read (ahci_hba_port_t * port , uint64_t start , uint32_t count , char * buf , ahci_hba_mem_t * abar );
418422
419423/**
420424 * @brief Query capacity (in bytes) from a SATA device using IDENTIFY data.
@@ -466,27 +470,206 @@ int storage_device_ahci_block_read(void* dev, uint64_t start, uint32_t bytes, un
466470 */
467471int storage_device_ahci_block_write (void * dev , uint64_t start , uint32_t bytes , const unsigned char * buffer );
468472
469-
473+ /**
474+ * @brief Wait until the AHCI port and attached device are ready to accept a new command.
475+ * @param port AHCI HBA port.
476+ * @return true if ready, false on timeout or fatal port state.
477+ */
470478bool wait_for_ready (ahci_hba_port_t * port );
479+
480+ /**
481+ * @brief Fill one PRDT entry in the command table.
482+ * @param cmdtbl Command table to modify.
483+ * @param index PRDT entry index to fill.
484+ * @param address Physical or DMA-able address of the data buffer.
485+ * @param byte_count Number of bytes to transfer (1..4MiB per entry, device-dependent).
486+ * @param interrupt Set true to request interrupt on completion for this PRDT entry.
487+ */
471488void fill_prdt (ahci_hba_cmd_tbl_t * cmdtbl , size_t index , void * address , uint32_t byte_count , bool interrupt );
489+
490+ /**
491+ * @brief Obtain and initialise a command header for a slot.
492+ * @param port AHCI HBA port.
493+ * @param slot Command slot number (0..31).
494+ * @param write Set true for host-to-device (write), false for device-to-host (read).
495+ * @param atapi Set true for ATAPI packet command, false for ATA.
496+ * @param prdtls Number of PRDT entries to advertise (PRDTL).
497+ * @return Pointer to the prepared command header.
498+ */
472499ahci_hba_cmd_header_t * get_cmdheader_for_slot (ahci_hba_port_t * port , size_t slot , bool write , bool atapi , uint16_t prdtls );
500+
501+ /**
502+ * @brief Return the command table for a header and clear CFIS/ATAPI/reserved regions.
503+ * @param cmdheader Command header whose table will be accessed.
504+ * @return Pointer to the command table.
505+ */
473506ahci_hba_cmd_tbl_t * get_and_clear_cmdtbl (ahci_hba_cmd_header_t * cmdheader );
507+
508+ /**
509+ * @brief Prepare a Register H2D FIS in the command table.
510+ * @param cmdtbl Command table to place the FIS into.
511+ * @param type FIS type (e.g., FIS_TYPE_REG_H2D).
512+ * @param command ATA/ATAPI command opcode.
513+ * @param feature_low Feature low byte.
514+ * @return Pointer to the FIS within the command table.
515+ */
474516ahci_fis_reg_h2d_t * setup_reg_h2d (ahci_hba_cmd_tbl_t * cmdtbl , uint8_t type , uint8_t command , uint8_t feature_low );
517+
518+ /**
519+ * @brief Fill LBA and sector count fields in a Register H2D FIS.
520+ * @param cmdfis Pointer to the FIS previously created by setup_reg_h2d.
521+ * @param start Starting LBA.
522+ * @param count Sector count (device logical block units).
523+ */
475524void fill_reg_h2c (ahci_fis_reg_h2d_t * cmdfis , uint64_t start , uint16_t count );
525+
526+ /**
527+ * @brief Issue a prepared command in the given slot by setting PxCI.
528+ * @param port AHCI HBA port.
529+ * @param slot Command slot number (0..31).
530+ */
476531void issue_command_to_slot (ahci_hba_port_t * port , uint8_t slot );
532+
533+ /**
534+ * @brief Wait for a command slot to complete and detect transport/taskfile errors.
535+ * @param port AHCI HBA port.
536+ * @param slot Command slot number (0..31).
537+ * @param function Short label used for diagnostics/logging.
538+ * @return true on success, false if a taskfile/transport error occurred (error already logged).
539+ */
477540bool wait_for_completion (ahci_hba_port_t * port , uint8_t slot , const char * function );
541+
542+ /**
543+ * @brief Convenience wrapper to issue a command and wait for completion.
544+ * @param port AHCI HBA port.
545+ * @param slot Command slot number (0..31).
546+ * @param function Short label used for diagnostics/logging.
547+ * @return true on success, false on error (error already logged).
548+ */
478549bool issue_and_wait (ahci_hba_port_t * port , uint8_t slot , const char * function );
550+
551+ /**
552+ * @brief Trim trailing ASCII spaces from a NUL-terminated string in place.
553+ * @param s String buffer to modify.
554+ */
479555void trim_trailing_spaces (char * s );
556+
557+ /**
558+ * @brief Build a human-readable ATAPI device label from INQUIRY data.
559+ * @param sd Storage device object to receive the label.
560+ * @param inq 36+ byte SCSI INQUIRY response buffer.
561+ */
480562void build_atapi_label (struct storage_device_t * sd , const uint8_t * inq );
481563
564+ /**
565+ * @brief Eject removable media from an ATAPI device (ALLOW removal then START STOP with LOEJ).
566+ * @param port AHCI HBA port for the device.
567+ * @param abar AHCI HBA memory (ABAR) pointer.
568+ * @return true on command acceptance, false on error (caller may fetch sense).
569+ */
482570bool atapi_eject (ahci_hba_port_t * port , ahci_hba_mem_t * abar );
483- bool ahci_read (ahci_hba_port_t * port , uint64_t start , uint32_t count , uint16_t * buf , ahci_hba_mem_t * abar );
484- bool ahci_write (ahci_hba_port_t * port , uint64_t start , uint32_t count , char * buf , ahci_hba_mem_t * abar );
485- bool ahci_atapi_read (ahci_hba_port_t * port , uint64_t start , uint32_t count , uint16_t * buf , ahci_hba_mem_t * abar );
486- uint64_t ahci_read_size (ahci_hba_port_t * port , ahci_hba_mem_t * abar );
571+
572+ /**
573+ * @brief Issue IDENTIFY (ATA or ATAPI) and copy the 512-byte identify page to out.
574+ * @param port AHCI HBA port.
575+ * @param abar AHCI HBA memory (ABAR) pointer.
576+ * @param out Destination buffer for identify data (512 bytes).
577+ * @return true on success, false on error.
578+ */
487579bool ahci_identify_page (ahci_hba_port_t * port , ahci_hba_mem_t * abar , uint8_t * out );
580+
581+ /**
582+ * @brief Issue ATAPI INQUIRY (0x12) and copy the response.
583+ * @param port AHCI HBA port.
584+ * @param abar AHCI HBA memory (ABAR) pointer.
585+ * @param out Destination buffer for INQUIRY data.
586+ * @param len Allocation length requested and number of bytes to copy.
587+ * @return true on success, false on error (caller may use sense mapping).
588+ */
488589bool atapi_enquiry (ahci_hba_port_t * port , ahci_hba_mem_t * abar , uint8_t * out , uint8_t len );
489590
591+ /**
592+ * @brief Map AHCI/AHCI-ATA/ATAPI latched status on a port to a fixed fs_error_t without performing I/O.
593+ * @param port AHCI HBA port; uses PxIS/PxSERR/PxTFD/PxSIG snapshots.
594+ * @return fs_error_t value describing the failure class.
595+ */
596+ int ahci_classify_error (ahci_hba_port_t * port );
597+
598+ /**
599+ * @brief Map SCSI/ATAPI sense (sense key, ASC, ASCQ) to a fixed fs_error_t.
600+ * @param sense_key SCSI sense key.
601+ * @param additional_sense_code Additional Sense Code (ASC).
602+ * @param additional_sense_code_qualifier Additional Sense Code Qualifier (ASCQ).
603+ * @return fs_error_t value describing the failure class.
604+ */
605+ int scsi_map_sense_to_fs_error (scsi_sense_key_t sense_key , scsi_additional_sense_code_t additional_sense_code , scsi_additional_sense_code_qualifier_t additional_sense_code_qualifier );
606+
607+ /**
608+ * @brief Issue ATAPI REQUEST SENSE (6) and copy sense data to the caller buffer.
609+ * @param port AHCI HBA port.
610+ * @param abar AHCI HBA memory (ABAR) pointer.
611+ * @param out Destination buffer for sense data.
612+ * @param out_len Allocation length requested (typically 18).
613+ * @return true on success, false on failure to obtain sense data.
614+ */
615+ bool atapi_request_sense6 (ahci_hba_port_t * port , ahci_hba_mem_t * abar , uint8_t * out , uint8_t out_len );
616+
617+ /**
618+ * @brief Extract sense key, ASC and ASCQ from a fixed-format (0x70/0x71) REQUEST SENSE buffer.
619+ * @param buf Sense buffer (>= 14 bytes, typically 18).
620+ * @param sense_key Output: sense key.
621+ * @param additional_sense_code Output: ASC.
622+ * @param additional_sense_code_qualifier Output: ASCQ.
623+ */
624+ void scsi_extract_fixed_sense (const uint8_t * buf , scsi_sense_key_t * sense_key , scsi_additional_sense_code_t * additional_sense_code , scsi_additional_sense_code_qualifier_t * additional_sense_code_qualifier );
625+
626+ /**
627+ * @brief Handle ATAPI CHECK CONDITION by issuing REQUEST SENSE, mapping to fs_error_t, logging a single line, and returning false.
628+ * @param port AHCI HBA port.
629+ * @param abar AHCI HBA memory (ABAR) pointer.
630+ * @param function Short label used for diagnostics/logging.
631+ * @return Always false to simplify call-sites that branch on failure.
632+ */
633+ bool atapi_handle_check_condition (ahci_hba_port_t * port , ahci_hba_mem_t * abar , const char * function );
634+
635+
636+ /**
637+ * @brief Map AHCI/AHCI-ATA/ATAPI status to a fixed fs_error_t.
638+ *
639+ * Uses PxIS priority: HBFS → HBDS → IFS → TFES. For TFES, inspects PxTFD ERR bits.
640+ * For ATAPI, returns FS_ERR_ATAPI_CHECK on TFES so the caller can issue REQUEST SENSE.
641+ *
642+ * This function performs no I/O; it only interprets the latched registers you pass in.
643+ */
644+ int ahci_classify_error (ahci_hba_port_t * port );
645+
646+ /**
647+ * @brief Map SCSI/ATAPI sense (SK/ASC/ASCQ) to fs_error_t with fixed message.
648+ */
649+ int scsi_map_sense_to_fs_error (scsi_sense_key_t sense_key , scsi_additional_sense_code_t additional_sense_code , scsi_additional_sense_code_qualifier_t additional_sense_code_qualifier );
650+
651+ /**
652+ * @brief Issue ATAPI REQUEST SENSE (6) and copy sense data to 'out'.
653+ * Expects 'out_len' >= 18 for standard fixed-format sense.
654+ * Returns true on success (command accepted and data DMA'd), false on failure.
655+ */
656+ bool atapi_request_sense6 (ahci_hba_port_t * port , ahci_hba_mem_t * abar , uint8_t * out , uint8_t out_len );
657+
658+ /**
659+ * @brief Extract SK/ASC/ASCQ from a fixed-format (0x70/0x71) REQUEST SENSE buffer.
660+ * Caller guarantees 'buf' points to at least 14 bytes (we usually pass 18).
661+ */
662+ void scsi_extract_fixed_sense (const uint8_t * buf , scsi_sense_key_t * sense_key , scsi_additional_sense_code_t * additional_sense_code , scsi_additional_sense_code_qualifier_t * additional_sense_code_qualifier );
663+
664+ /**
665+ * @brief Convenience helper for ATAPI CHECK CONDITION paths.
666+ * Issues REQUEST SENSE, extracts and maps sense, logs a single line, then returns false.
667+ *
668+ * Always returns false so call-sites can simply: if (!atapi_handle_check_condition(...)) return false;
669+ * If REQUEST SENSE itself fails, logs a generic timeout/hardware error.
670+ */
671+ bool atapi_handle_check_condition (ahci_hba_port_t * port , ahci_hba_mem_t * abar , const char * function );
672+
490673/* ----------------------------- Layout sanity checks ----------------------------- */
491674
492675/** @brief Compile-time size check: command header must be 0x20 bytes. */
0 commit comments