ata.go
func ataWrite(r *ATAArg, rs io.ReadSeeker) (*ATAArg, error) {
	// Only ATA writes allowed here
	if r.CmdStatus != ATACmdStatusWrite28Bit && r.CmdStatus != ATACmdStatusWrite48Bit {
		return nil, errATAAbort
	}

	// Write must be flagged as a write
	if !r.FlagWrite {
		return nil, errATAAbort
	}

	// Verify that request data and sector count match up
	if sectors := len(r.Data) / sectorSize; sectors != int(r.SectorCount) {
		return nil, errATAAbort
	}

	// Determine if io.ReadSeeker is also an io.Writer, and if a write is
	// requested
	rws, ok := rs.(io.ReadWriteSeeker)
	if !ok {
		// A write was requested, but the io.ReadSeeker is not an io.Writer
		return nil, errATAAbort
	}

	// TODO(mdlayher): implement asynchronous writes

	// Convert LBA to byte offset and seek to correct location
	offset := calculateLBA(r.LBA, r.FlagLBA48Extended) * sectorSize
	if _, err := rs.Seek(offset, os.SEEK_SET); err != nil {
		return nil, err
	}

	// Write data to stream
	n, err := rws.Write(r.Data)
	if err != nil {
		return nil, err
	}

	// Verify full sectors written to disk using sector count
	if sectors := n / sectorSize; sectors != int(r.SectorCount) {
		return nil, errATAAbort
	}

	return &ATAArg{
		CmdStatus: ATACmdStatusReadyStatus,
	}, nil
}
func ataWrite(r *ATAArg, rs io.ReadSeeker) (*ATAArg, error) {
	// Only ATA writes allowed here
	if r.CmdStatus != ATACmdStatusWrite28Bit && r.CmdStatus != ATACmdStatusWrite48Bit {
		return nil, errATAAbort
	}

	// Write must be flagged as a write
	if !r.FlagWrite {
		return nil, errATAAbort
	}

	// Verify that request data and sector count match up
	if sectors := len(r.Data) / sectorSize; sectors != int(r.SectorCount) {
		return nil, errATAAbort
	}

	// Determine if io.ReadSeeker is also an io.Writer, and if a write is
	// requested
	rws, ok := rs.(io.ReadWriteSeeker)
	if !ok {
		// A write was requested, but the io.ReadSeeker is not an io.Writer
		return nil, errATAAbort
	}

	// TODO(mdlayher): implement asynchronous writes

	// Convert LBA to byte offset and seek to correct location
	offset := calculateLBA(r.LBA, r.FlagLBA48Extended) * sectorSize
	if _, err := rs.Seek(offset, os.SEEK_SET); err != nil {
		return nil, err
	}

	// Write data to stream
	n, err := rws.Write(r.Data)
	if err != nil {
		return nil, err
	}

	// Verify full sectors written to disk using sector count
	if sectors := n / sectorSize; sectors != int(r.SectorCount) {
		return nil, errATAAbort
	}

	return &ATAArg{
		CmdStatus: ATACmdStatusReadyStatus,
	}, nil
}
// ataWrite performs an ATA 28-bit or 48-bit write request on rs using the
// argument values in r.